/** * OpenKM, Open Document Management System (http://www.openkm.com) * Copyright (c) 2006-2011 Paco Avila & Josep Llort * * No bytes were intentionally harmed during the development of this application. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ package com.openkm.principal; import java.text.MessageFormat; import java.util.ArrayList; import java.util.Hashtable; import java.util.Iterator; import java.util.List; import javax.naming.Context; import javax.naming.NamingEnumeration; import javax.naming.NamingException; import javax.naming.directory.Attribute; import javax.naming.directory.Attributes; import javax.naming.directory.DirContext; import javax.naming.directory.InitialDirContext; import javax.naming.directory.SearchControls; import javax.naming.directory.SearchResult; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.openkm.core.Config; /** * http://forums.sun.com/thread.jspa?threadID=581444 * http://java.sun.com/docs/books/tutorial/jndi/ops/filter.html * http://www.openkm.com/Configuration/903-Rejavac-cannot-find-symbol-PrincipalAdapter.html */ public class LdapPrincipalAdapter implements PrincipalAdapter { private static Logger log = LoggerFactory.getLogger(LdapPrincipalAdapter.class); @Override public List<String> getUsers() throws PrincipalAdapterException { log.debug("getUsers()"); List<String> list = new ArrayList<String>(); List<String> ldap = ldapSearch( Config.PRINCIPAL_LDAP_SERVER, Config.PRINCIPAL_LDAP_SECURITY_PRINCIPAL, Config.PRINCIPAL_LDAP_SECURITY_CREDENTIALS, Config.PRINCIPAL_LDAP_USER_SEARCH_BASE, Config.PRINCIPAL_LDAP_USER_SEARCH_FILTER, Config.PRINCIPAL_LDAP_USER_ATTRIBUTE); for (Iterator<String> it = ldap.iterator(); it.hasNext(); ) { String user = it.next(); if (!Config.SYSTEM_USER.equals(user)) { if (Config.SYSTEM_LOGIN_LOWERCASE) { user = user.toLowerCase(); } list.add(user); } } log.debug("getUsers: {}", list); return list; } @Override public List<String> getRoles() throws PrincipalAdapterException { log.debug("getRoles()"); List<String> list = new ArrayList<String>(); List<String> ldap = ldapSearch( Config.PRINCIPAL_LDAP_SERVER, Config.PRINCIPAL_LDAP_SECURITY_PRINCIPAL, Config.PRINCIPAL_LDAP_SECURITY_CREDENTIALS, Config.PRINCIPAL_LDAP_ROLE_SEARCH_BASE, Config.PRINCIPAL_LDAP_ROLE_SEARCH_FILTER, Config.PRINCIPAL_LDAP_ROLE_ATTRIBUTE); for (Iterator<String> it = ldap.iterator(); it.hasNext(); ) { String role = it.next(); list.add(role); } log.debug("getRoles: {}", list); return list; } @Override public String getMail(String user) throws PrincipalAdapterException { log.debug("getMail({})", user); String mail = null; List<String> ldap = ldapSearch( Config.PRINCIPAL_LDAP_SERVER, Config.PRINCIPAL_LDAP_SECURITY_PRINCIPAL, Config.PRINCIPAL_LDAP_SECURITY_CREDENTIALS, MessageFormat.format(Config.PRINCIPAL_LDAP_MAIL_SEARCH_BASE, user), MessageFormat.format(Config.PRINCIPAL_LDAP_MAIL_SEARCH_FILTER, user), Config.PRINCIPAL_LDAP_MAIL_ATTRIBUTE); if (!ldap.isEmpty()) { mail = ldap.get(0); } log.debug("getMail: {}", mail); return mail; } @Override public String getName(String user) throws PrincipalAdapterException { return LdapPrincipalAdapter.class.getCanonicalName(); } @Override public List<String> getUsersByRole(String role) throws PrincipalAdapterException { log.debug("getUsersByRole({})", role); List<String> list = new ArrayList<String>(); List<String> ldap = ldapSearch( Config.PRINCIPAL_LDAP_SERVER, Config.PRINCIPAL_LDAP_SECURITY_PRINCIPAL, Config.PRINCIPAL_LDAP_SECURITY_CREDENTIALS, MessageFormat.format(Config.PRINCIPAL_LDAP_USERS_BY_ROLE_SEARCH_BASE, role), MessageFormat.format(Config.PRINCIPAL_LDAP_USERS_BY_ROLE_SEARCH_FILTER, role), Config.PRINCIPAL_LDAP_USERS_BY_ROLE_ATTRIBUTE); for (Iterator<String> it = ldap.iterator(); it.hasNext(); ) { String user = it.next(); if (!Config.SYSTEM_USER.equals(user)) { if (Config.SYSTEM_LOGIN_LOWERCASE) { user = user.toLowerCase(); } list.add(user); } } log.debug("getUsersByRole: {}", list); return list; } @Override public List<String> getRolesByUser(String user) throws PrincipalAdapterException { log.debug("getRolesByUser({})", user); List<String> list = new ArrayList<String>(); List<String> ldap = ldapSearch( Config.PRINCIPAL_LDAP_SERVER, Config.PRINCIPAL_LDAP_SECURITY_PRINCIPAL, Config.PRINCIPAL_LDAP_SECURITY_CREDENTIALS, MessageFormat.format(Config.PRINCIPAL_LDAP_ROLES_BY_USER_SEARCH_BASE, user), MessageFormat.format(Config.PRINCIPAL_LDAP_ROLES_BY_USER_SEARCH_FILTER, user), Config.PRINCIPAL_LDAP_ROLES_BY_USER_ATTRIBUTE); for (Iterator<String> it = ldap.iterator(); it.hasNext(); ) { String role = it.next(); list.add(role); } log.debug("getRolesByUser: {}", list); return list; } /** * LDAP Search */ public List<String> ldapSearch(String url, String principal, String credentials, String searchBase, String searchFilter, String attribute) { log.debug("ldapSearch({}, {}, {}, {}, {}, {})", new Object[] { url, principal, credentials, searchBase, searchFilter, attribute } ); List<String> al = new ArrayList<String>(); Hashtable<String, String> env = new Hashtable<String, String>(); env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory"); env.put(Context.SECURITY_AUTHENTICATION, "simple"); env.put(Context.PROVIDER_URL, url); // Optional is some cases (Max OS/X) if (!principal.equals("")) env.put(Context.SECURITY_PRINCIPAL, principal); if (!credentials.equals("")) env.put(Context.SECURITY_CREDENTIALS, credentials); try { DirContext ctx = new InitialDirContext(env); SearchControls searchCtls = new SearchControls(); searchCtls.setSearchScope(SearchControls.SUBTREE_SCOPE); NamingEnumeration<SearchResult> results = ctx.search(searchBase, searchFilter, searchCtls); while (results.hasMore()) { SearchResult searchResult = (SearchResult) results.next(); Attributes attributes = searchResult.getAttributes(); if (attribute.equals("")) { StringBuilder sb = new StringBuilder(); for (NamingEnumeration<?> ne = attributes.getAll(); ne.hasMore(); ) { Attribute attr = (Attribute) ne.nextElement(); sb.append(attr.toString()); sb.append("\n"); } al.add(sb.toString()); } else { Attribute attrib = attributes.get(attribute); if (attrib != null) { // Handle multi-value attributes for (NamingEnumeration<?> ne = attrib.getAll(); ne.hasMore(); ) { String value = (String) ne.nextElement(); // If FQDN get only main part if (value.startsWith("CN=") || value.startsWith("cn=")) { String cn = value.substring(3, value.indexOf(',')); log.debug("FQDN: {}, CN: {}", value, cn); al.add(cn); } else { al.add(value); } } } } } ctx.close(); } catch (NamingException e) { e.printStackTrace(); } log.debug("ldapSearch: {}", al); return al; } }