/* * Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.ldap; import org.springframework.ldap.core.DirContextAdapter; import org.springframework.ldap.core.DistinguishedName; import org.springframework.security.crypto.codec.Utf8; import org.springframework.util.Assert; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import javax.naming.Context; import javax.naming.NamingEnumeration; import javax.naming.NamingException; import java.net.URI; import java.net.URISyntaxException; /** * LDAP Utility methods. * * @author Luke Taylor */ public final class LdapUtils { // ~ Static fields/initializers // ===================================================================================== private static final Log logger = LogFactory.getLog(LdapUtils.class); // ~ Constructors // =================================================================================================== private LdapUtils() { } // ~ Methods // ======================================================================================================== public static void closeContext(Context ctx) { if (ctx instanceof DirContextAdapter) { return; } try { if (ctx != null) { ctx.close(); } } catch (NamingException e) { logger.error("Failed to close context.", e); } } public static void closeEnumeration(NamingEnumeration ne) { try { if (ne != null) { ne.close(); } } catch (NamingException e) { logger.error("Failed to close enumeration.", e); } } /** * Obtains the part of a DN relative to a supplied base context. * <p> * If the DN is "cn=bob,ou=people,dc=springframework,dc=org" and the base context name * is "ou=people,dc=springframework,dc=org" it would return "cn=bob". * </p> * * @param fullDn the DN * @param baseCtx the context to work out the name relative to. * * @return the * * @throws NamingException any exceptions thrown by the context are propagated. */ public static String getRelativeName(String fullDn, Context baseCtx) throws NamingException { String baseDn = baseCtx.getNameInNamespace(); if (baseDn.length() == 0) { return fullDn; } DistinguishedName base = new DistinguishedName(baseDn); DistinguishedName full = new DistinguishedName(fullDn); if (base.equals(full)) { return ""; } Assert.isTrue(full.startsWith(base), "Full DN does not start with base DN"); full.removeFirst(base); return full.toString(); } /** * Gets the full dn of a name by prepending the name of the context it is relative to. * If the name already contains the base name, it is returned unaltered. */ public static DistinguishedName getFullDn(DistinguishedName dn, Context baseCtx) throws NamingException { DistinguishedName baseDn = new DistinguishedName(baseCtx.getNameInNamespace()); if (dn.contains(baseDn)) { return dn; } baseDn.append(dn); return baseDn; } public static String convertPasswordToString(Object passObj) { Assert.notNull(passObj, "Password object to convert must not be null"); if (passObj instanceof byte[]) { return Utf8.decode((byte[]) passObj); } else if (passObj instanceof String) { return (String) passObj; } else { throw new IllegalArgumentException( "Password object was not a String or byte array."); } } /** * Works out the root DN for an LDAP URL. * <p> * For example, the URL <tt>ldap://monkeymachine:11389/dc=springframework,dc=org</tt> * has the root DN "dc=springframework,dc=org". * </p> * * @param url the LDAP URL * * @return the root DN */ public static String parseRootDnFromUrl(String url) { Assert.hasLength(url, "url must have length"); String urlRootDn; if (url.startsWith("ldap:") || url.startsWith("ldaps:")) { URI uri = parseLdapUrl(url); urlRootDn = uri.getRawPath(); } else { // Assume it's an embedded server urlRootDn = url; } if (urlRootDn.startsWith("/")) { urlRootDn = urlRootDn.substring(1); } return urlRootDn; } /** * Parses the supplied LDAP URL. * @param url the URL (e.g. * <tt>ldap://monkeymachine:11389/dc=springframework,dc=org</tt>). * @return the URI object created from the URL * @throws IllegalArgumentException if the URL is null, empty or the URI syntax is * invalid. */ private static URI parseLdapUrl(String url) { Assert.hasLength(url, "url must have length"); try { return new URI(url); } catch (URISyntaxException e) { IllegalArgumentException iae = new IllegalArgumentException( "Unable to parse url: " + url); iae.initCause(e); throw iae; } } }