package railo.runtime.net.ldap; import java.io.IOException; import java.security.Security; import java.util.Enumeration; import java.util.Hashtable; 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; import javax.naming.ldap.InitialLdapContext; import railo.commons.lang.ClassException; import railo.commons.lang.ClassUtil; import railo.commons.lang.StringUtil; import railo.runtime.exp.PageException; import railo.runtime.op.Caster; import railo.runtime.type.Collection; import railo.runtime.type.KeyImpl; import railo.runtime.type.Query; import railo.runtime.type.QueryImpl; import railo.runtime.type.util.ListUtil; import com.sun.net.ssl.internal.ssl.Provider; /** * Ldap Client */ public final class LDAPClient { /** * Field <code>SECURE_NONE</code> */ public static final short SECURE_NONE=0; /** * Field <code>SECURE_CFSSL_BASIC</code> */ public static final short SECURE_CFSSL_BASIC=1; /** * Field <code>SECURE_CFSSL_CLIENT_AUTH</code> */ public static final short SECURE_CFSSL_CLIENT_AUTH=2; /** * Field <code>SORT_TYPE_CASE</code> */ public static final int SORT_TYPE_CASE = 0; /** * Field <code>SORT_TYPE_NOCASE</code> */ public static final int SORT_TYPE_NOCASE = 1; /** * Field <code>SORT_DIRECTION_ASC</code> */ public static final int SORT_DIRECTION_ASC = 0; /** * Field <code>SORT_DIRECTION_DESC</code> */ public static final int SORT_DIRECTION_DESC = 1; Hashtable env=new Hashtable(); /** * constructor of the class * @param server * @param port * @param binaryColumns */ public LDAPClient(String server, int port,String[] binaryColumns) { env.put("java.naming.factory.initial", "com.sun.jndi.ldap.LdapCtxFactory"); env.put("java.naming.provider.url", "ldap://" + server+":"+port); // rEAD AS bINARY for(int i = 0; i < binaryColumns.length; i++)env.put("java.naming.ldap.attributes.binary", binaryColumns[i]); // Referral env.put("java.naming.referral", "ignore"); } /** * sets username password for the connection * @param username * @param password */ public void setCredential(String username, String password) { if(username != null) { env.put("java.naming.security.principal", username); env.put("java.naming.security.credentials", password); } else { env.remove("java.naming.security.principal"); env.remove("java.naming.security.credentials"); } } /** * sets the secure Level * @param secureLevel [SECURE_CFSSL_BASIC, SECURE_CFSSL_CLIENT_AUTH, SECURE_NONE] * @throws ClassNotFoundException * @throws ClassException */ public void setSecureLevel(short secureLevel) throws ClassException { // Security if(secureLevel==SECURE_CFSSL_BASIC) { env.put("java.naming.security.protocol", "ssl"); env.put("java.naming.ldap.factory.socket", "javax.net.ssl.SSLSocketFactory"); //Class.orName("com.sun.net.ssl.internal.ssl.Provider"); ClassUtil.loadClass("com.sun.net.ssl.internal.ssl.Provider"); Security.addProvider(new Provider()); } else if(secureLevel==SECURE_CFSSL_CLIENT_AUTH) { env.put("java.naming.security.protocol", "ssl"); env.put("java.naming.security.authentication", "EXTERNAL"); } else { env.put("java.naming.security.authentication", "simple"); env.remove("java.naming.security.protocol"); env.remove("java.naming.ldap.factory.socket"); } } /** * sets thr referral * @param referral */ public void setReferral(int referral) { if(referral > 0) { env.put("java.naming.referral", "follow"); env.put("java.naming.ldap.referral.limit", Caster.toString(referral)); } else { env.put("java.naming.referral", "ignore"); env.remove("java.naming.ldap.referral.limit"); } } /** * adds LDAP entries to LDAP server * @param dn * @param attributes * @param delimiter * @throws NamingException * @throws PageException */ public void add(String dn, String attributes, String delimiter, String seperator) throws NamingException, PageException { DirContext ctx = new InitialDirContext(env); ctx.createSubcontext(dn, toAttributes(attributes,delimiter,seperator)); ctx.close(); } /** * deletes LDAP entries on an LDAP server * @param dn * @throws NamingException */ public void delete(String dn) throws NamingException{ DirContext ctx = new InitialDirContext(env); ctx.destroySubcontext(dn); ctx.close(); } /** * modifies distinguished name attribute for LDAP entries on LDAP server * @param dn * @param attributes * @throws NamingException */ public void modifydn(String dn, String attributes) throws NamingException{ DirContext ctx = new InitialDirContext(env); ctx.rename(dn, attributes); ctx.close(); } public void modify(String dn, int modifytype, String strAttributes, String delimiter, String separator) throws NamingException, PageException { DirContext context = new InitialDirContext(env); String strArrAttributes[] = toStringAttributes(strAttributes,delimiter); int count = 0; for(int i=0; i<strArrAttributes.length; i++) { String[] attributesValues = getAttributesValues(strArrAttributes[i], separator); if(attributesValues == null)count++; else count+=attributesValues.length; } ModificationItem modItems[] = new ModificationItem[count]; BasicAttribute basicAttr = null; int k = 0; for(int i = 0; i < strArrAttributes.length; i++) { String attribute = strArrAttributes[i]; String type = getAttrValueType(attribute); String values[] = getAttributesValues(attribute,separator); if(modifytype==DirContext.REPLACE_ATTRIBUTE) { if(values == null) basicAttr = new BasicAttribute(type); else basicAttr = new BasicAttribute(type, values[0]); modItems[k] = new ModificationItem(modifytype, basicAttr); k++; if(values != null && values.length > 1) { for(int j = 1; j < values.length; j++) { basicAttr = new BasicAttribute(type, values[j]); modItems[k] = new ModificationItem(DirContext.ADD_ATTRIBUTE, basicAttr); k++; } } } else { for(int j = 0; j < values.length; j++) { if(type != null || modifytype==DirContext.ADD_ATTRIBUTE) basicAttr = new BasicAttribute(type, values[j]); else basicAttr = new BasicAttribute(values[j]); modItems[k] = new ModificationItem(modifytype, basicAttr); k++; } } } context.modifyAttributes(dn, modItems); context.close(); } /** * @param dn * @param strAttributes * @param scope * @param startrow * @param maxrows * @param timeout * @param sort * @param sortType * @param sortDirection * @param start * @param separator * @param filter * @return * @throws NamingException * @throws PageException * @throws IOException */ public Query query(String strAttributes,int scope, int startrow, int maxrows, int timeout, String[] sort, int sortType, int sortDirection, String start, String separator, String filter) throws NamingException, PageException, IOException { //strAttributes=strAttributes.trim(); boolean attEQAsterix=strAttributes.trim().equals("*"); String[] attributes = attEQAsterix?new String[]{"name","value"}:toStringAttributes(strAttributes,","); // Control SearchControls controls = new SearchControls(); controls.setReturningObjFlag(true); controls.setSearchScope(scope); if(!attEQAsterix)controls.setReturningAttributes(toStringAttributes(strAttributes,",")); if(maxrows>0)controls.setCountLimit(startrow + maxrows + 1); if(timeout>0)controls.setTimeLimit(timeout); InitialLdapContext context = new InitialLdapContext(env, null); // Search Query qry=new QueryImpl(attributes,0,"query"); try { NamingEnumeration results = context.search(start, filter, controls); // Fill result int row=1; if(!attEQAsterix) { while(results.hasMoreElements()) { SearchResult resultRow = (SearchResult)results.next(); if(row++<startrow)continue; int len=qry.addRow(); NamingEnumeration rowEnum = resultRow.getAttributes().getAll(); String dn = resultRow.getNameInNamespace(); qry.setAtEL("dn",len,dn); while(rowEnum.hasMore()) { Attribute attr = (Attribute)rowEnum.next(); Collection.Key key = KeyImpl.init(attr.getID()); Enumeration values = attr.getAll(); Object value; String existing,strValue; while(values.hasMoreElements()) { value = values.nextElement(); strValue=Caster.toString(value,null); existing=Caster.toString(qry.getAt(key, len,null),null); if(!StringUtil.isEmpty(existing) && !StringUtil.isEmpty(strValue)) { value = existing + separator + strValue; } else if(!StringUtil.isEmpty(existing)) value = existing; qry.setAtEL(key,len,value); } } if(maxrows>0 && len>=maxrows)break; } } else { outer:while(results.hasMoreElements()) { SearchResult resultRow = (SearchResult)results.next(); if(row++<startrow)continue; Attributes attributesRow = resultRow.getAttributes(); NamingEnumeration rowEnum = attributesRow.getIDs(); while(rowEnum.hasMoreElements()) { int len=qry.addRow(); String name = Caster.toString(rowEnum.next()); Object value=null; try { value=attributesRow.get(name).get(); }catch(Exception e) {} qry.setAtEL("name",len,name); qry.setAtEL("value",len,value); if(maxrows>0 && len>=maxrows)break outer; } qry.setAtEL("name",qry.size(),"dn"); } } } finally { context.close(); } // Sort if(sort!=null && sort.length>0) { int order = sortDirection==SORT_DIRECTION_ASC ? Query.ORDER_ASC : Query.ORDER_DESC; for(int i=sort.length-1;i>=0;i--) { String item=sort[i]; if(item.indexOf(' ')!=-1)item=ListUtil.first(item," ",true); qry.sort(KeyImpl.getInstance(item),order); //keys[i] = new SortKey(item); } } return qry; } private static String[] toStringAttributes(String strAttributes,String delimiter) throws PageException { return ListUtil.toStringArrayTrim(ListUtil.listToArrayRemoveEmpty(strAttributes,delimiter)); } private static Attributes toAttributes(String strAttributes,String delimiter, String separator) throws PageException { String[] arrAttr = toStringAttributes(strAttributes,delimiter); BasicAttributes attributes = new BasicAttributes(); for(int i=0; i<arrAttr.length; i++) { String strAttr = arrAttr[i]; // Type int eqIndex=strAttr.indexOf('='); Attribute attr = new BasicAttribute((eqIndex != -1)?strAttr.substring(0, eqIndex).trim():null); // Value String strValue = (eqIndex!=-1)?strAttr.substring( eqIndex+ 1):strAttr; String[] arrValue=ListUtil.toStringArray(ListUtil.listToArrayRemoveEmpty(strValue,separator)); // Fill for(int y=0; y<arrValue.length; y++) { attr.add(arrValue[y]); } attributes.put(attr); } return attributes; } private String getAttrValueType(String attribute) { int eqIndex=attribute.indexOf("="); if(eqIndex != -1) return attribute.substring(0, eqIndex).trim(); return null; } private String[] getAttributesValues(String attribute, String separator) throws PageException { String strValue = attribute.substring(attribute.indexOf("=") + 1); if(strValue.length() == 0) return null; return ListUtil.toStringArray(ListUtil.listToArrayRemoveEmpty(strValue,separator.equals(", ") ? "," : separator)); } }