8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package com.sun.jndi.ldap; 27 28 import java.util.Hashtable; 29 import java.util.Vector; 30 import java.util.Enumeration; 31 32 import javax.naming.*; 33 import javax.naming.directory.*; 34 import javax.naming.spi.ObjectFactory; 35 import javax.naming.spi.InitialContextFactory; 36 import javax.naming.ldap.Control; 37 38 import com.sun.jndi.url.ldap.ldapURLContextFactory; 39 40 final public class LdapCtxFactory implements ObjectFactory, InitialContextFactory { 41 /** 42 * The type of each address in an LDAP reference. 43 */ 44 public final static String ADDRESS_TYPE = "URL"; 45 46 // ----------------- ObjectFactory interface -------------------- 47 48 public Object getObjectInstance(Object ref, Name name, Context nameCtx, 49 Hashtable<?,?> env) throws Exception { 50 141 System.arraycopy(urls, 0, urls2, 0, size); 142 return urls2; 143 } 144 145 // ------------ Utilities used by other classes ---------------- 146 147 public static DirContext getLdapCtxInstance(Object urlInfo, Hashtable<?,?> env) 148 throws NamingException { 149 150 if (urlInfo instanceof String) { 151 return getUsingURL((String)urlInfo, env); 152 } else if (urlInfo instanceof String[]) { 153 return getUsingURLs((String[])urlInfo, env); 154 } else { 155 throw new IllegalArgumentException( 156 "argument must be an LDAP URL String or array of them"); 157 } 158 } 159 160 private static DirContext getUsingURL(String url, Hashtable<?,?> env) 161 throws NamingException { 162 DirContext ctx = null; 163 LdapURL ldapUrl = new LdapURL(url); 164 String dn = ldapUrl.getDN(); 165 String host = ldapUrl.getHost(); 166 int port = ldapUrl.getPort(); 167 String[] hostports; 168 String domainName = null; 169 170 // handle a URL with no hostport (ldap:/// or ldaps:///) 171 // locate the LDAP service using the URL's distinguished name 172 if (host == null && 173 port == -1 && 174 dn != null && 175 (domainName = ServiceLocator.mapDnToDomainName(dn)) != null && 176 (hostports = ServiceLocator.getLdapService(domainName, env)) 177 != null) { 178 // Generate new URLs that include the discovered hostports. 179 // Reuse the original URL scheme. 180 String scheme = ldapUrl.getScheme() + "://"; 181 String[] newUrls = new String[hostports.length]; 182 String query = ldapUrl.getQuery(); 183 String urlSuffix = ldapUrl.getPath() + (query != null ? query : ""); 184 for (int i = 0; i < hostports.length; i++) { 185 newUrls[i] = scheme + hostports[i] + urlSuffix; 186 } 187 ctx = getUsingURLs(newUrls, env); 188 // Associate the derived domain name with the context 189 ((LdapCtx)ctx).setDomainName(domainName); 190 191 } else { 192 ctx = new LdapCtx(dn, host, port, env, ldapUrl.useSsl()); 193 // Record the URL that created the context 194 ((LdapCtx)ctx).setProviderUrl(url); 195 } 196 return ctx; 197 } 198 199 /* 200 * Try each URL until one of them succeeds. 201 * If all URLs fail, throw one of the exceptions arbitrarily. 202 * Not pretty, but potentially more informative than returning null. 203 */ 204 private static DirContext getUsingURLs(String[] urls, Hashtable<?,?> env) 205 throws NamingException { 206 NamingException ne = null; 207 DirContext ctx = null; 208 for (int i = 0; i < urls.length; i++) { 209 try { 210 return getUsingURL(urls[i], env); 211 } catch (AuthenticationException e) { 212 throw e; 213 } catch (NamingException e) { 214 ne = e; 215 } 216 } 217 throw ne; 218 } 219 220 /** 221 * Used by Obj and obj/RemoteToAttrs too so must be public 222 */ 223 public static Attribute createTypeNameAttr(Class<?> cl) { 224 Vector<String> v = new Vector<>(10); 225 String[] types = getTypeNames(cl, v); 226 if (types.length > 0) { 227 BasicAttribute tAttr = 228 new BasicAttribute(Obj.JAVA_ATTRIBUTES[Obj.TYPENAME]); 229 for (int i = 0; i < types.length; i++) { 230 tAttr.add(types[i]); | 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package com.sun.jndi.ldap; 27 28 import java.lang.reflect.Constructor; 29 import java.security.AccessController; 30 import java.security.PrivilegedAction; 31 import java.util.Hashtable; 32 import java.util.List; 33 import java.util.Vector; 34 import java.util.Enumeration; 35 import java.util.function.BiFunction; 36 37 import javax.naming.*; 38 import javax.naming.directory.*; 39 import javax.naming.spi.ObjectFactory; 40 import javax.naming.spi.InitialContextFactory; 41 import javax.naming.ldap.Control; 42 43 import com.sun.jndi.url.ldap.ldapURLContextFactory; 44 45 final public class LdapCtxFactory implements ObjectFactory, InitialContextFactory { 46 /** 47 * The type of each address in an LDAP reference. 48 */ 49 public final static String ADDRESS_TYPE = "URL"; 50 51 // ----------------- ObjectFactory interface -------------------- 52 53 public Object getObjectInstance(Object ref, Name name, Context nameCtx, 54 Hashtable<?,?> env) throws Exception { 55 146 System.arraycopy(urls, 0, urls2, 0, size); 147 return urls2; 148 } 149 150 // ------------ Utilities used by other classes ---------------- 151 152 public static DirContext getLdapCtxInstance(Object urlInfo, Hashtable<?,?> env) 153 throws NamingException { 154 155 if (urlInfo instanceof String) { 156 return getUsingURL((String)urlInfo, env); 157 } else if (urlInfo instanceof String[]) { 158 return getUsingURLs((String[])urlInfo, env); 159 } else { 160 throw new IllegalArgumentException( 161 "argument must be an LDAP URL String or array of them"); 162 } 163 } 164 165 private static DirContext getUsingURL(String url, Hashtable<?,?> env) 166 throws NamingException 167 { 168 NamingException ne = new NamingException(); 169 DirContext ctx; 170 try { 171 List<String> urls = getDnsUrls(url, env); 172 if (urls.size() == 0) { 173 String factory; 174 if (env.contains(LdapCtx.DNS_PROVIDER)) { 175 factory = (String) env.get(LdapCtx.DNS_PROVIDER); 176 } else { 177 factory = "com.sun.jndi.ldap.DefaultDnsProvider"; 178 } 179 throw new NamingException( 180 factory + " was unable to resolve a valid ldap url"); 181 } 182 183 for (String u : urls) { 184 LdapURL ldapUrl = new LdapURL(u); 185 String dn = ldapUrl.getDN(); 186 String host = ldapUrl.getHost(); 187 int port = ldapUrl.getPort(); 188 ctx = new LdapCtx(dn, host, port, env, ldapUrl.useSsl()); 189 // Record the URL that created the context 190 ((LdapCtx) ctx).setProviderUrl(u); 191 return ctx; 192 } 193 } catch (Exception e) { 194 ne.setRootCause(e); 195 } 196 throw ne; 197 } 198 199 @SuppressWarnings("unchecked") 200 private static List<String> getDnsUrls(String url, Hashtable<?,?> env) 201 throws Exception 202 { 203 BiFunction<String, Hashtable<?,?>, List<String>> dnsProvider = null; 204 205 if (env.containsKey(LdapCtx.DNS_PROVIDER)) { 206 PrivilegedAction<ClassLoader> act = 207 Thread.currentThread()::getContextClassLoader; 208 ClassLoader cl = AccessController.doPrivileged(act); 209 Class<?> cls = Class.forName( 210 (String) env.get(LdapCtx.DNS_PROVIDER), true, cl); 211 Constructor<?> ctor = cls.getConstructor(); 212 dnsProvider = 213 (BiFunction<String, Hashtable<?,?>, List<String>>) ctor.newInstance(); 214 } 215 216 if (dnsProvider == null) { 217 dnsProvider = new DefaultLdapDnsProvider(); 218 } 219 220 return dnsProvider.apply(url, env); 221 } 222 223 /* 224 * Try each URL until one of them succeeds. 225 * If all URLs fail, throw one of the exceptions arbitrarily. 226 * Not pretty, but potentially more informative than returning null. 227 */ 228 private static DirContext getUsingURLs(String[] urls, Hashtable<?,?> env) 229 throws NamingException 230 { 231 NamingException ne = new NamingException(); 232 DirContext ctx; 233 for (String u : urls) { 234 try { 235 ctx = getUsingURL(u, env); 236 LdapURL ldapUrl = new LdapURL(u); 237 // Associate the derived domain name with the context 238 ((LdapCtx) ctx).setDomainName( 239 ServiceLocator.mapDnToDomainName(ldapUrl.getDN())); 240 return ctx; 241 } catch (AuthenticationException e) { 242 throw e; 243 } catch (NamingException e) { 244 ne = e; 245 } 246 } 247 throw ne; 248 } 249 250 /** 251 * Used by Obj and obj/RemoteToAttrs too so must be public 252 */ 253 public static Attribute createTypeNameAttr(Class<?> cl) { 254 Vector<String> v = new Vector<>(10); 255 String[] types = getTypeNames(cl, v); 256 if (types.length > 0) { 257 BasicAttribute tAttr = 258 new BasicAttribute(Obj.JAVA_ATTRIBUTES[Obj.TYPENAME]); 259 for (int i = 0; i < types.length; i++) { 260 tAttr.add(types[i]); |