base.ldap.LdapHelper Maven / Gradle / Ivy
/**
* Creative commons Attribution-NonCommercial license.
*
* http://creativecommons.org/licenses/by-nc/2.5/au/deed.en_GB
*
* NO WARRANTY IS GIVEN OR IMPLIED, USE AT YOUR OWN RISK.
*/
package base.ldap;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.naming.Context;
import javax.naming.NameClassPair;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.Attribute;
import javax.naming.directory.Attributes;
import javax.naming.directory.BasicAttribute;
import javax.naming.directory.BasicAttributes;
import javax.naming.directory.DirContext;
import javax.naming.directory.InitialDirContext;
import javax.naming.directory.ModificationItem;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;
/**
* Manages connecting to an LDAP server and executing
* basic LDAP commands.
*
* Querying the OID LDAP server:
*
* LdapHelper ldap = new LdapHelper("ldap://sso-dev.portal.unimelb.edu.au:9327/", "cn=orcladmin,cn=Users,c=portal,o=unimelb,dc=edu,dc=au", "password");
* for(String item : ldap.find("ou=people,o=unimelb", "(&(objectclass=person)(uid=gmtest*))"))
* System.out.println(" - " + item);
*
*
* Querying the Centaur LDAP server:
*
*
* LdapHelper ldap = new LdapHelper("ldaps://centaur.unimelb.edu.au:636/", "uid=username,ou=people,o=unimelb", "password", true);
* for(String item : ldap.find("ou=people,o=unimelb", "(&(objectclass=person)(uid=gmtest*))"))
* System.out.println(" - " + item);
*
*
*/
public class LdapHelper {
private DirContext ctx;
/**
* Initialise an LdapHelper wrapper to a specific LDAP server
*
* @param url JDBC url, ie ldaps://servername.com:689
* @param username LDAP username
* @param password LDAP password
* @param trusting When true, SSL certificate validation should be bypassed.
*/
public LdapHelper(String url, String username, String password, boolean trusting) throws NamingException {
Hashtable env = new Hashtable<>();
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.PROVIDER_URL, url);
env.put(Context.SECURITY_PRINCIPAL, username);
env.put(Context.SECURITY_CREDENTIALS, password);
if(trusting) {
env.put("java.naming.ldap.factory.socket", "base.ssl.TrustingSslSocketFactory");
}
ctx = new InitialDirContext(env);
}
/**
* This method has been renamed, see getChildren()
*
* @param dn
* @return
* @throws IOException
* @deprecated Deprecated in favour of getChildren()
* @see getChildren()
*/
@Deprecated
public List list(String dn) throws IOException {
return getChildren(dn);
}
/**
* Fetch the set of LDAP object sitting below this object in the ldap tree.
*
* @param dn Full dn of the parent object
* @return List of full dn strings for each child object
* @throws IOException
*/
public List getChildren(String dn) throws IOException {
List names = new ArrayList<>();
NamingEnumeration items;
try {
items = ctx.list(dn);
while(items.hasMore()) {
NameClassPair item = items.next();
names.add(item.getName());
}
} catch (NamingException e) {
throw new IOException(e);
}
return names;
}
public Map getAttributes(String dn) throws IOException {
Map attributes = new Hashtable<>();
try {
Attributes result = ctx.getAttributes(dn);
NamingEnumeration extends Attribute> items = result.getAll();
while(items.hasMore()) {
Attribute item = (Attribute)items.next();
if(item.size() > 0) {
String c = attributes.get(item.getID());
for(int i = 0; i < item.size(); i++) {
if(c == null) {
c = "";
}
if(c.length() > 0) {
c = c + "|";
}
try {
c = c + (String)item.get(i);
} catch(java.lang.ClassCastException e) {
Logger.getLogger(LdapHelper.class.getName()).log(Level.WARNING, "Ignoring LDAP attribute that cant be cast to String: " + item.getID(), e);
}
}
attributes.put(item.getID(), c);
} else {
if(item.get() instanceof String) {
attributes.put(item.getID(), (String)item.get());
}
}
}
} catch (NamingException e) {
throw new IOException(e);
}
return attributes;
}
/**
* Check if a DN exists on the ldap server.
*
* @param dn Unique DN to check
* @return True if DN exists
* @throws IOException
*/
public boolean exists(String dn) throws IOException {
try {
ctx.lookup(dn);
return true;
} catch (javax.naming.NameNotFoundException e) {
return false;
} catch (NamingException e) {
throw new IOException(e);
}
}
/**
* Find the full unique DN of a person, where the username matches the cn field.
* @param base DN containing the people we wish to search
* @param username The value of the persons 'cn' attribute
* @return Unique DN of this person, or null if not found.
* @throws IOException
*/
public String findPersonDN(String base, String username) throws IOException {
try {
SearchControls ctls = new SearchControls();
ctls.setSearchScope(SearchControls.SUBTREE_SCOPE);
NamingEnumeration answer = ctx.search(base, "(&(objectclass=person)(cn="+username+"))", ctls);
if (answer.hasMore()) {
SearchResult sr = (SearchResult)answer.next();
answer.close();
return sr.getNameInNamespace();
}
answer.close();
} catch(javax.naming.PartialResultException e) {
System.out.println("Warning: "+e.getMessage());
} catch (NamingException e) {
throw new IOException(e);
}
return null;
}
public String getGroupDN(String base, String group) throws IOException {
try {
SearchControls ctls = new SearchControls();
ctls.setSearchScope(SearchControls.SUBTREE_SCOPE);
NamingEnumeration answer = ctx.search(base, "(&(objectclass=group)(cn=*"+group+"*))", ctls);
if (answer.hasMore()) {
SearchResult sr = (SearchResult)answer.next();
answer.close();
return sr.getNameInNamespace();
}
answer.close();
} catch(javax.naming.PartialResultException e) {
System.out.println("Warning: "+e.getMessage());
} catch (NamingException e) {
throw new IOException(e);
}
return null;
}
/**
* Search the entire LDAP server using a filter
*
* @param filter The search filter
* @return List of dn strings for each object that matches the filter
* @throws IOException
*/
public List find(String filter) throws IOException {
List names = new ArrayList();
try {
SearchControls ctls = new SearchControls();
ctls.setSearchScope(SearchControls.SUBTREE_SCOPE);
NamingEnumeration answer = ctx.search("", filter, ctls);
while (answer.hasMore()) {
SearchResult sr = (SearchResult)answer.next();
names.add(sr.getNameInNamespace());
}
answer.close();
} catch (NamingException e) {
throw new IOException(e);
}
return names;
}
/**
* Search the entire LDAP server using a filter
*
* @param baseDn The do a subtree search starting from this location
* @param filter The search filter
* @return List of dn strings for each object that matches the filter
* @throws IOException
*/
public List find(String baseDn, String filter) throws IOException {
List names = new ArrayList();
try {
SearchControls ctls = new SearchControls();
ctls.setSearchScope(SearchControls.SUBTREE_SCOPE);
NamingEnumeration answer = ctx.search(baseDn, filter, ctls);
while (answer.hasMore()) {
SearchResult sr = (SearchResult)answer.next();
names.add(sr.getNameInNamespace());
}
answer.close();
} catch (NamingException e) {
throw new IOException(e);
}
return names;
}
public void add(String dn, String schemas, Map attributes) throws IOException {
Attributes newAttributes = new BasicAttributes(true);
Attribute oc = new BasicAttribute("objectclass");
for(String oclass : schemas.split(",")) {
oc.add(oclass);
}
newAttributes.put(oc);
for(String attribute : attributes.keySet()) {
newAttributes.put(new BasicAttribute(attribute, attributes.get(attribute)));
}
try {
ctx.createSubcontext(dn, newAttributes);
} catch (NamingException e) {
throw new IOException(e);
}
}
/**
* Remove an entry from the LDAP server, including all associated attributes and
* children objects
*
* @param dn The DN of the object being removed.
* @throws IOException
*/
public void delete(String dn) throws IOException {
try {
ctx.destroySubcontext(dn);
} catch (NamingException e) {
throw new IOException(e);
}
}
public void addMemberToGroup(String userDn, String groupDn) throws IOException {
ModificationItem[] mods = new ModificationItem[1];
Attribute mod0 = new BasicAttribute("member", userDn);
mods[0] = new ModificationItem(DirContext.ADD_ATTRIBUTE, mod0);
try {
ctx.modifyAttributes(groupDn, mods);
} catch (javax.naming.NameAlreadyBoundException e) {
throw new IOException(e);
} catch (NamingException e) {
throw new IOException(e);
}
}
public void removeMemberFromGroup(String userDn, String groupDn) throws IOException {
ModificationItem[] mods = new ModificationItem[1];
Attribute mod0 = new BasicAttribute("member", userDn);
mods[0] = new ModificationItem(DirContext.REMOVE_ATTRIBUTE, mod0);
try {
ctx.modifyAttributes(groupDn, mods);
} catch (javax.naming.NameAlreadyBoundException e) {
throw new IOException(e);
} catch (NamingException e) {
throw new IOException(e);
}
}
/**
* Depreciated in favour of using the more generic getMultivalueAttribute() call. Use
* the following instead:
*
*
* ldap.getMultivalueAttribute(dn, "member");
*
*
* @param dn
* @return
* @throws IOException
* @deprecated Deprecated in favour of using ldap.getMultivalueAttribute(dn, "member")
*/
@Deprecated
public List getGroupMembers(String dn) throws IOException {
return getMultivalueAttribute(dn, "member");
}
public List getMultivalueAttribute(String dn, String attribute) throws IOException {
List members = new ArrayList();
try {
Attributes result = ctx.getAttributes(dn);
NamingEnumeration extends Attribute> items = result.getAll();
while(items.hasMore()) {
Attribute item = (Attribute)items.next();
if(item.getID().equalsIgnoreCase(attribute)) {
for(int i = 0; i < item.size(); i++) {
members.add((String)item.get(i));
}
}
}
} catch (NamingException e) {
throw new IOException(e);
}
return members;
}
public List getPersonMembership(String dn) throws IOException {
List members = new ArrayList();
try {
Attributes result = ctx.getAttributes(dn);
NamingEnumeration extends Attribute> items = result.getAll();
while(items.hasMore()) {
Attribute item = (Attribute)items.next();
if(item.getID().equalsIgnoreCase("memberOf")) {
for(int i = 0; i < item.size(); i++) {
members.add((String)item.get(i));
}
}
}
} catch (NamingException e) {
throw new IOException(e);
}
return members;
}
public void modifyAttribute(String dn, String attribute, String value) throws IOException {
ModificationItem[] mods = new ModificationItem[1];
Attribute mod0 = new BasicAttribute(attribute, value);
mods[0] = new ModificationItem(DirContext.REPLACE_ATTRIBUTE, mod0);
try {
ctx.modifyAttributes(dn, mods);
} catch (javax.naming.NameAlreadyBoundException e) {
throw new IOException(e);
} catch (NamingException e) {
throw new IOException(e);
}
}
public void addAttribute(String dn, String attribute, String value) throws IOException {
ModificationItem[] mods = new ModificationItem[1];
Attribute mod0 = new BasicAttribute(attribute, value);
mods[0] = new ModificationItem(DirContext.ADD_ATTRIBUTE, mod0);
try {
ctx.modifyAttributes(dn, mods);
} catch (javax.naming.NameAlreadyBoundException e) {
throw new IOException(e);
} catch (NamingException e) {
throw new IOException(e);
}
}
public void removeAttribute(String dn, String attribute) throws IOException {
ModificationItem[] mods = new ModificationItem[1];
Attribute mod0 = new BasicAttribute(attribute, null);
mods[0] = new ModificationItem(DirContext.REMOVE_ATTRIBUTE, mod0);
try {
ctx.modifyAttributes(dn, mods);
} catch (javax.naming.NameAlreadyBoundException e) {
throw new IOException(e);
} catch (NamingException e) {
throw new IOException(e);
}
}
/**
* Remove an individual value from a multi-value attribute.
*
* @param dn
* @param attribute
* @param value
* @throws IOException
*/
public void removeAttribute(String dn, String attribute, String value) throws IOException {
ModificationItem[] mods = new ModificationItem[1];
Attribute mod0 = new BasicAttribute(attribute, value);
mods[0] = new ModificationItem(DirContext.REMOVE_ATTRIBUTE, mod0);
try {
ctx.modifyAttributes(dn, mods);
} catch (javax.naming.NameAlreadyBoundException e) {
throw new IOException(e);
} catch (NamingException e) {
throw new IOException(e);
}
}
public static String ldapEscape(String escape) {
escape = escape.replaceAll("\\\\", "\\\\\\\\");
escape = escape.replaceAll(",", "\\\\,");
escape = escape.replaceAll("#", "\\\\#");
escape = escape.replaceAll("\\+", "\\\\+");
escape = escape.replaceAll("<", "\\\\<");
escape = escape.replaceAll(">", "\\\\>");
escape = escape.replaceAll(";", "\\\\;");
escape = escape.replaceAll("=", "\\\\=");
return escape;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy