package org.jblooming.ldap; import org.jblooming.utilities.StringUtilities; import org.jblooming.utilities.JSP; import org.jblooming.utilities.file.FileUtilities; import org.jblooming.waf.settings.ApplicationState; import org.jblooming.waf.configuration.LoaderSupport; import org.jblooming.waf.constants.Fields; import org.jblooming.security.LdapUser; import org.jblooming.anagraphicalData.AnagraphicalData; import org.jblooming.PlatformRuntimeException; import org.jblooming.tracer.Tracer; import javax.naming.directory.*; import javax.naming.NamingException; import javax.naming.NamingEnumeration; import javax.naming.Context; import javax.naming.AuthenticationException; import java.util.*; import java.io.File; public class LdapUtilities { //Active Directory Attributes public static String USER_PRINCIPAL_NAME = "userPrincipalName"; public static String ACCOUNTNAME = "sAMAccountName"; public static String SID = "objectSID"; public static String EMAIL = "mail"; public static String DESCRIPTION = "name"; public static String SURNAME = "sn"; public static String FIRSTNAME = "givenName"; public static String PHONE = "telephoneNumber"; public static String COUNTRY = "co"; public static String CITY = "l"; public static String ZIP = "postalCode"; public static String MOBILE = "mobile"; public static String STATE = "st"; public static String USERSEARCHFILTER = "(objectClass=user)"; public static String GROUPSEARCHFILTER = "(objectClass=memberOf)"; public static String GROUPATTRIBUTE = "memberOf"; public static final String LDAP = "LDAP_"; public static final String LDAP_CONFIG_FILE = LDAP + "CONFIG_FILE"; public static final String INITIAL_CONTEXT_FACTORY = LDAP + "INITIAL_CONTEXT_FACTORY"; public static final String PROVIDER_URL = LDAP + "PROVIDER_URL"; public static final String SECURITY_AUTHENTICATION = LDAP + "SECURITY_AUTHENTICATION"; public static final String SECURITY_PRINCIPAL = LDAP + "SECURITY_PRINCIPAL"; public static final String SECURITY_CREDENTIALS = LDAP + "SECURITY_CREDENTIALS"; public static final String BASE_DN = LDAP + "BASE_DN"; public static final String DOMAIN_NAME = LDAP + "DOMAIN_NAME"; public static final String ENABLE_LDAP_SSL = LDAP + "ENABLE_LDAP_SSL"; public static final String CREATE_USERS_ON_LOGIN = LDAP + "CREATE_USERS_ON_LOGIN"; public static final String CREATE_USERS_IN_AREA = LDAP + "CREATE_USERS_IN_AREA"; //ldap account constants private static int UF_ACCOUNTDISABLE = 0x0002; private static int UF_PASSWD_NOTREQD = 0x0020; private static int UF_PASSWD_CANT_CHANGE = 0x0040; private static int UF_NORMAL_ACCOUNT = 0x0200; private static int UF_DONT_EXPIRE_PASSWD = 0x10000; private static int UF_PASSWORD_EXPIRED = 0x800000; public static List<String> getMemberOf(String baseDN, String cn, DirContext ctx, List<String> groups) throws NamingException { SearchControls ctls = new SearchControls(); ctls.setCountLimit(1); ctls.setSearchScope(SearchControls.SUBTREE_SCOPE); ctls.setReturningAttributes(new String[]{"memberof"}); NamingEnumeration nm = ctx.search(baseDN, cn, ctls); if (nm != null && nm.hasMoreElements()) { SearchResult sr = (SearchResult) nm.nextElement(); Attributes atts = sr.getAttributes(); NamingEnumeration allAttr = atts.getAll(); if (allAttr != null && allAttr.hasMore()) { if (groups == null) groups = new ArrayList<String>(); Attribute att = (Attribute) allAttr.next(); NamingEnumeration attEn = att.getAll(); while (attEn.hasMore()) { String groupSer = (String) attEn.next(); String group = StringUtilities.splitToArray(groupSer, ",")[0]; if (!groups.contains(group)) groups.add(group); getMemberOf(baseDN, group, ctx, groups); } } } return groups; } public static Map<String, Set<String>> getPropertyOf(String baseDN, String cn, DirContext ctx) throws NamingException { SearchControls ctls = new SearchControls(); ctls.setCountLimit(1); ctls.setSearchScope(SearchControls.SUBTREE_SCOPE); NamingEnumeration nm = ctx.search(baseDN, cn, ctls); Map<String, Set<String>> props = new HashMap<String, Set<String>>(); if (nm.hasMoreElements()) { SearchResult sr = (SearchResult) nm.nextElement(); props = getProperty(sr); } return props; } public static Map<String, Set<String>> getProperty(SearchResult sr) throws NamingException { Map<String, Set<String>> props = new HashMap<String, Set<String>>(); Attributes atts = sr.getAttributes(); NamingEnumeration allAttr = atts.getAll(); while (allAttr.hasMore()) { Attribute att = (Attribute) allAttr.next(); String propId = att.getID(); Set<String> propValSet = new HashSet<String>(); NamingEnumeration attEn = att.getAll(); if (attEn != null && attEn.hasMore()) { while (attEn.hasMore()) { propValSet.add(attEn.next() + ""); } } else { propValSet.add(att.get().toString()); } props.put(propId, propValSet); } return props; } public static LdapUser getLdapUser(SearchResult srt) throws NamingException { LdapUser ldapUser = new LdapUser(); Attributes attrs = srt.getAttributes(); if (attrs.get(ACCOUNTNAME) != null) ldapUser.setUsername((String) attrs.get(ACCOUNTNAME).get()); if (attrs.get(FIRSTNAME) != null) ldapUser.setName((String) attrs.get(FIRSTNAME).get()); if (attrs.get(SURNAME) != null) ldapUser.setSurname((String) attrs.get(SURNAME).get()); if (attrs.get(EMAIL) != null) ldapUser.setEmail((String) attrs.get(EMAIL).get()); if (attrs.get(STATE) != null) ldapUser.setState((String) attrs.get(STATE).get()); if (attrs.get(CITY) != null) ldapUser.setCity((String) attrs.get(CITY).get()); if (attrs.get(COUNTRY) != null) ldapUser.setCountry((String) attrs.get(COUNTRY).get()); if (attrs.get(ZIP) != null) ldapUser.setZip((String) attrs.get(ZIP).get()); if (attrs.get(PHONE) != null) ldapUser.setTelephone((String) attrs.get(PHONE).get()); if (attrs.get(MOBILE) != null) ldapUser.setMobile((String) attrs.get(MOBILE).get()); Long userAccountControl; if (attrs.get("userAccountControl") != null) { userAccountControl = Long.parseLong((String) attrs.get("userAccountControl").get()); if ((userAccountControl & UF_ACCOUNTDISABLE) == UF_ACCOUNTDISABLE) { ldapUser.setEnabled(false); } else { ldapUser.setEnabled(true); } } if (attrs.get(USER_PRINCIPAL_NAME) != null) ldapUser.setUserPrincipalName((String) attrs.get(USER_PRINCIPAL_NAME).get()); return ldapUser; } public static Vector<LdapUser> getLdapUsers(NamingEnumeration<SearchResult> sr) throws NamingException { Vector<LdapUser> ldapUsers = new Vector<LdapUser>(); while (sr.hasMoreElements()) { SearchResult srt = sr.next(); ldapUsers.add(getLdapUser(srt)); } return ldapUsers; } public static boolean checkConnection() { try { DirContext ctx = getDefaultContext(); if (ctx == null) return false; } catch (AuthenticationException auth) { Tracer.platformLogger.error(auth); } catch (NamingException ne) { Tracer.platformLogger.error(ne); } return true; } public static HashMap<String, String> getGroups(String basedn, String filter, DirContext ctx, int countLimit) throws NamingException { SearchControls ctls = new SearchControls(); ctls.setSearchScope(SearchControls.SUBTREE_SCOPE); //ctls.setReturningAttributes(new String[]{"memberof"}); ctls.setReturningAttributes(new String[]{LdapUtilities.GROUPATTRIBUTE}); HashMap<String, String> groups = new HashMap(); NamingEnumeration nm = ctx.search(basedn, filter, ctls); while (nm != null && nm.hasMoreElements()) { SearchResult sr = (SearchResult) nm.nextElement(); Attributes atts = sr.getAttributes(); Attribute att = atts.get(LdapUtilities.GROUPATTRIBUTE); if (att != null) { NamingEnumeration attEn = att.getAll(); while (attEn.hasMore()) { String groupSer = (String) attEn.next(); String group = StringUtilities.splitToArray(groupSer, ",")[0]; if (groups.get(groupSer) == null) groups.put(groupSer, group); } } } return groups; } public static DirContext getContext(String provider_url, String security_auth, String security_principal, String security_credentials) throws NamingException { if (provider_url.toLowerCase().indexOf("ldap://") == -1 && provider_url.toLowerCase().indexOf("ldaps://") == -1) provider_url = "ldap://" + provider_url; /* if (security_principal.toLowerCase().indexOf("@") == -1) security_principal = security_principal + "@" + domain; */ Hashtable env = new Hashtable(); //ldap and SSL if (Fields.TRUE.equals(ApplicationState.getApplicationSetting(ENABLE_LDAP_SSL))) { String keystore = System.getProperty("java.home") + File.separator +"lib" + File.separator +"security"+File.separator +"cacerts"; //System.setProperty(LDAPConstants.LDAP_SSL_TRUST_STORE,keystore); System.setProperty("javax.net.ssl.trustStore", keystore); env.put(Context.SECURITY_PROTOCOL, "ssl"); } env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory"); env.put(Context.PROVIDER_URL, provider_url); env.put(Context.SECURITY_AUTHENTICATION, security_auth); env.put(Context.SECURITY_PRINCIPAL, security_principal); env.put(Context.SECURITY_CREDENTIALS, security_credentials); DirContext ctx = new InitialDirContext(env); return ctx; } public static LdapUser getLdapUser(String loginName, DirContext dc) throws NamingException { LdapUser result = null; if (JSP.ex(loginName)) { SearchControls ctls = new SearchControls(); ctls.setSearchScope(SearchControls.SUBTREE_SCOPE); NamingEnumeration nm = dc.search(ApplicationState.getApplicationSetting(BASE_DN), ACCOUNTNAME + "=" + loginName, ctls); //hack for active directory /*if (nm!=null && !nm.hasMore() && "administrator".equals(loginName)) { loginName = "Administrator"; nm = dc.search(ApplicationState.getApplicationSetting(BASE_DN), ACCOUNTNAME + "=" + loginName, ctls); }*/ if (nm != null && nm.hasMore()) { result = getLdapUsers(nm).get(0); } } return result; } public static DirContext getDefaultContext() throws NamingException { String secCr = ApplicationState.getApplicationSetting(LdapUtilities.SECURITY_CREDENTIALS); if (JSP.ex(secCr)) { return getContext(ApplicationState.getApplicationSetting(PROVIDER_URL), ApplicationState.getApplicationSetting(SECURITY_AUTHENTICATION), ApplicationState.getApplicationSetting(SECURITY_PRINCIPAL), StringUtilities.decrypt(ApplicationState.getApplicationSetting(SECURITY_CREDENTIALS))); } else return null; } public static String getFilterForDisableUsers() { return "(!(userAccountControl:1.2.840.113556.1.4.803:=2))"; } public static Vector<LdapUser> getUsers(String filterGroups, String additionalFilter, String basedn, DirContext ctx) { Vector<LdapUser> users = null; String filter = null; //additionalFilter = "(objectClass=*)"; if (filterGroups != null) filter = filterGroups; if (additionalFilter != null) { if (filter != null && filter.length() > 0) filter = "(&" + additionalFilter + filter + ")"; else filter = additionalFilter; } if (filter == null) return users; SearchControls sc = new SearchControls(); sc.setSearchScope(SearchControls.SUBTREE_SCOPE); try { NamingEnumeration<SearchResult> sr = ctx.search(basedn, filter, sc); users = getLdapUsers(sr); } catch (NamingException ne) { Tracer.platformLogger.error(ne); } return users; } public static String checkUser(String prov_url, String domain, String sec_principal, String sec_auth, String sec_credentials) { String errorMsg = null; try { if (prov_url.toLowerCase().indexOf("ldap://") == -1 && prov_url.toLowerCase().indexOf("ldaps://") == -1) prov_url = "ldap://" + prov_url; DirContext ctx = LdapUtilities.getDefaultContext(); SearchControls sc = new SearchControls(); sc.setSearchScope(SearchControls.SUBTREE_SCOPE); NamingEnumeration<SearchResult> sr = ctx.search(ApplicationState.getApplicationSetting(BASE_DN), USER_PRINCIPAL_NAME + "=" + sec_principal, sc); SearchResult rs = sr.next(); if (rs != null) {// the usrname is valid and extract the CN attribute String cnValue = rs.getNameInNamespace(); ctx = LdapUtilities.getContext(prov_url, sec_auth, cnValue, sec_credentials); } } catch (AuthenticationException auth) { Tracer.platformLogger.error(auth); errorMsg = "Connection Refused Principal or Credential invalid."; } catch (NamingException ne) { Tracer.platformLogger.error(ne); errorMsg = "Connection Refused Authentication Not Supported."; } catch (Throwable e) { Tracer.platformLogger.error(e); errorMsg = "Connection Refused: maybe username not found :-("; } return errorMsg; } public static void makeAD(LdapUser user, AnagraphicalData anag) { if (user.getEmail() != null) anag.setEmail(user.getEmail()); if (user.getTelephone() != null) anag.setTelephone(user.getTelephone()); if (user.getMobile() != null) anag.setMobile(user.getMobile()); if (user.getCity() != null) anag.setCity(user.getCity()); if (user.getCountry() != null) anag.setCountry(user.getCountry()); if (user.getZip() != null) anag.setZip(user.getZip()); if (user.getState() != null) anag.setProvince(user.getState()); } public static Properties loadLdapMappingFromFile() { String ldapFileName = ApplicationState.getApplicationSetting(LdapUtilities.LDAP_CONFIG_FILE); if (!JSP.ex(ldapFileName)) ldapFileName = "activeDirectory.properties"; String globalPath = ApplicationState.webAppFileSystemRootPath + File.separator + "commons" + File.separator + "settings" + File.separator + "ldap" + File.separator + ldapFileName; HashMap<String, String> ldapSettings = new HashMap<String, String>(); File global = new File(globalPath); Properties properties = null; if (global.exists()) { properties = FileUtilities.getProperties(globalPath); } else throw new PlatformRuntimeException("LDAP properties file not found: " + global.getAbsolutePath()); for (Object name : properties.keySet()) { String key = (String) name; if (!key.startsWith("#")) ldapSettings.put(key, (String) properties.get(name)); } //Read explicit mapping to default properties if (properties.getProperty("ACCOUNTNAME") != null) ACCOUNTNAME = properties.getProperty("ACCOUNTNAME"); if (properties.getProperty("USERPRINCIPALNAME") != null) USER_PRINCIPAL_NAME = properties.getProperty("USERPRINCIPALNAME"); if (properties.getProperty("FIRSTNAME") != null) FIRSTNAME = properties.getProperty("FIRSTNAME"); if (properties.getProperty("SURNAME") != null) SURNAME = properties.getProperty("SURNAME"); if (properties.getProperty("EMAIL") != null) EMAIL = properties.getProperty("EMAIL"); //Ldap Additional fields if (properties.getProperty("PHONE") != null) PHONE = properties.getProperty("PHONE"); if (properties.getProperty("MOBILE") != null) MOBILE = properties.getProperty("MOBILE"); if (properties.getProperty("COUNTRY") != null) COUNTRY = properties.getProperty("COUNTRY"); if (properties.getProperty("STATE") != null) STATE = properties.getProperty("STATE"); if (properties.getProperty("ZIP") != null) ZIP = properties.getProperty("ZIP"); if (properties.getProperty("CITY") != null) CITY = properties.getProperty("CITY"); if (properties.getProperty("USERSEARCHFILTER") != null) USERSEARCHFILTER = properties.getProperty("USERSEARCHFILTER"); if (properties.getProperty("GROUPSEARCHFILTER") != null) GROUPSEARCHFILTER = properties.getProperty("GROUPSEARCHFILTER"); ApplicationState.applicationParameters.put("LDAP", ldapSettings); return properties; } }