/* $Id$ */ /** * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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.apache.manifoldcf.core.auth; import java.util.Hashtable; import javax.naming.Context; import javax.naming.NamingEnumeration; import javax.naming.NamingException; import javax.naming.directory.DirContext; import javax.naming.directory.InitialDirContext; import javax.naming.directory.SearchControls; import javax.naming.directory.SearchResult; import org.apache.commons.lang.StringUtils; import org.apache.manifoldcf.core.interfaces.IAuth; import org.apache.manifoldcf.core.interfaces.IThreadContext; import org.apache.manifoldcf.core.system.Logging; import org.apache.manifoldcf.core.system.ManifoldCF; import org.apache.manifoldcf.core.interfaces.ManifoldCFException; import org.apache.manifoldcf.core.interfaces.LockManagerFactory; public class LdapAuthenticator implements IAuth { private static final String CONTEXT_FACTORY = "com.sun.jndi.ldap.LdapCtxFactory"; private static final String PROVIDER_URL_PROPERTY = "org.apache.manifoldcf.login.ldap.providerurl"; private static final String SECURITY_AUTHENTICATION_TYPE = "org.apache.manifoldcf.login.ldap.securityauthenticationtype"; private static final String SECURITY_PRINCIPLE = "org.apache.manifoldcf.login.ldap.securityprincipal"; private static final String CONTEXT_SEARCH_QUERY = "org.apache.manifoldcf.login.ldap.contextsearchquery"; private static final String SEARCH_ATTRIBUTE = "org.apache.manifoldcf.login.ldap.searchattribute"; protected final String securityPrincipal; protected final String securityAuthenticationType; protected final String providerURLProperty; protected final String contextSearchQuery; protected final String searchAttribute; /** Constructor */ public LdapAuthenticator(final IThreadContext threadContext) throws ManifoldCFException { securityPrincipal = LockManagerFactory.getStringProperty(threadContext,SECURITY_PRINCIPLE,""); securityAuthenticationType = LockManagerFactory.getStringProperty(threadContext,SECURITY_AUTHENTICATION_TYPE,"simple"); providerURLProperty = LockManagerFactory.getStringProperty(threadContext,PROVIDER_URL_PROPERTY,""); contextSearchQuery = LockManagerFactory.getStringProperty(threadContext,CONTEXT_SEARCH_QUERY,""); searchAttribute = LockManagerFactory.getStringProperty(threadContext,SEARCH_ATTRIBUTE,"uid"); } /** * @param userID * @param password * @return */ private Hashtable<String, String> buildEnvironment(String userID, String password) { Hashtable<String, String> environment = new Hashtable<String, String>(); environment.put(Context.INITIAL_CONTEXT_FACTORY, CONTEXT_FACTORY); environment.put(Context.PROVIDER_URL, providerURLProperty); environment.put(Context.SECURITY_AUTHENTICATION, securityAuthenticationType); environment.put( Context.SECURITY_PRINCIPAL, substituteUser(securityPrincipal, userID)); environment.put(Context.SECURITY_CREDENTIALS, password); return environment; } /** * @param source * @param substitution * @return */ private static String substituteUser(String source, String substitution) { return source.replace("$(userID)", substitution); } /** * @param userId * @param password * @return */ @Override public boolean verifyUILogin(final String userId, final String password) throws ManifoldCFException { return verifyLogin(userId, password); } @Override public boolean verifyAPILogin(final String userId, final String password) throws ManifoldCFException { return verifyLogin(userId, password); } protected boolean verifyLogin(final String userId, final String password) throws ManifoldCFException { boolean authenticated = false; if (StringUtils.isNotEmpty(userId) && StringUtils.isNotEmpty(password)) { try { Logging.misc .info("Authentication attempt for user = " + userId); // Create initial context DirContext ctx = new InitialDirContext(buildEnvironment(userId, password)); NamingEnumeration results = null; try { SearchControls controls = new SearchControls(); controls.setSearchScope(SearchControls.SUBTREE_SCOPE); results = ctx .search("", substituteUser(contextSearchQuery, userId), controls); // is the user in the group? while (results.hasMore()) { SearchResult searchResult = (SearchResult) results .next(); if (userId.equals(searchResult.getAttributes() .get(searchAttribute) .get())) { Logging.misc.info("Successfully authenticated : " + userId); authenticated = true; break; } } } catch (Exception e) { Logging.misc.error("User not authenticated = " + userId + " exception = " + e.getMessage(), e); throw new ManifoldCFException("User not authenticated: "+e.getMessage(),e); } finally { if (results != null) { try { results.close(); } catch (Exception e) { // do nothing } } if (ctx != null) { try { ctx.close(); } catch (Exception e) { // do nothing } } } } catch (NamingException e) { Logging.misc.error("Exception authenticating user = " + userId + " exception = " + e.getMessage(), e); throw new ManifoldCFException("Exception authenticating user: "+e.getMessage(),e); } } return authenticated; } /** Check user capability */ public boolean checkCapability(final String userId, final int capability) throws ManifoldCFException { // No current ability to distinguish roles return true; } }