/* * Atricore IDBus * * Copyright (c) 2009, Atricore Inc. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This software 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ package org.atricore.idbus.idojos.ldapidentitystore; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.atricore.idbus.kernel.main.authn.*; import org.atricore.idbus.kernel.main.store.AbstractStore; import org.atricore.idbus.kernel.main.store.SimpleUserKey; import org.atricore.idbus.kernel.main.store.UserKey; import org.atricore.idbus.kernel.main.store.exceptions.NoSuchUserException; import org.atricore.idbus.kernel.main.store.exceptions.SSOIdentityException; import javax.naming.Context; import javax.naming.NamingEnumeration; import javax.naming.NamingException; import javax.naming.directory.*; import javax.naming.ldap.Control; import javax.naming.ldap.InitialLdapContext; import java.lang.reflect.Array; import java.nio.ByteBuffer; import java.nio.CharBuffer; import java.nio.charset.CharacterCodingException; import java.nio.charset.Charset; import java.nio.charset.CharsetDecoder; import java.util.*; /** * An implementation of an Identity and Credential Store which obtains credential, user and * role information from an LDAP server using JNDI, based on the configuration properties. * <p/> * It allows to set whatever options your LDAP JNDI provider supports your Gateway * configuration file. * Examples of standard property names are: * <ul> * <li><code>initialContextFactory = "java.naming.factory.initial"</code> * <li><code>securityProtocol = "java.naming.security.protocol"</code> * <li><code>providerUrl = "java.naming.provider.url"</code> * <li><code>securityAuthentication = "java.naming.security.authentication"</code> * </ul> * <p/> * This store implementation is both an Identity Store and Credential Store. * Since in JOSSO the authentication of the user is left to the configured Authentication Scheme, * this store implementation cannot delegate user identity assertion by binding to the * LDAP server. For that reason it retrieves the required credentials from the directory * leaving the authentication procedure to the configured Authentication Scheme. * The store must be supplied with the configuratoin parameters so that it can retrieve user * identity information. * <p/> * <p/> * Additional component properties include: * <ul> * <li>securityPrincipal: the DN of the user to be used to bind to the LDAP Server * <li>securityCredential: the securityPrincipal password to be used for binding to the * LDAP Server. * <li>securityAuthentication: the security level to be used with the LDAP Server session. * Its value is one of the following strings: * "none", "simple", "strong". * If not set, "simple" will be used. * <li>ldapSearchScope : alows control over LDAP search scope : valid values are ONELEVEL, SUBTREE</li> * <li>usersCtxDN : the fixed distinguished name to the context to search for user accounts. * <li>principalUidAttributeID: the name of the attribute that contains the user login name. * This is used to locate the user. * <li>rolesCtxDN : The fixed distinguished name to the context to search for user roles. * <li>uidAttributeID: the name of the attribute that, in the object containing the user roles, * references role members. The attribute value should be the DN of the user associated with the * role. This is used to locate the user roles. * <li>roleAttributeID : The name of the attribute that contains the role name * <li>roleMatchingMOde : The way JOSSO gets users roles, values UDN (default) and UID. * <li>credentialQueryString : The query string to obtain user credentials. It should have the * following format : user_attribute_name=credential_attribute_name,... * For example : * uid=username,userPassword=password * <li>userPropertiesQueryString : The query string to obtain user properties. It should have * the following format : ldap_attribute_name=user_attribute_name,... * For example : * mail=mail,cn=description * </ul> * A sample LDAP Identity Store configuration : * <p/> * <pre> * <sso-identity-store> * <class>org.josso.gateway.identity.service.store.ldap.LDAPIdentityStore</class> * <initialContextFactory>com.sun.jndi.ldap.LdapCtxFactory</initialContextFactory> * <providerUrl>ldap://localhost</providerUrl> * <securityPrincipal>cn=Manager\,dc=my-domain\,dc=com</securityPrincipal> * <securityCredential>secret</securityCredential> * <securityAuthentication>simple</securityAuthentication> * <usersCtxDN>ou=People\,dc=my-domain\,dc=com</usersCtxDN> * <principalUidAttributeID>uid</principalUidAttributeID> * <rolesCtxDN>ou=Roles\,dc=my-domain\,dc=com</rolesCtxDN> * <uidAttributeID>uniquemember</uidAttributeID> * <roleMatchingMode>UDN</roleMatchingMode> * <roleAttributeID>cn</roleAttributeID> * <credentialQueryString>uid=username\,userPassword=password</credentialQueryString> * <userPropertiesQueryString>mail=mail\,cn=description</userPropertiesQueryString> * <ldapSearchScope>SUBTREE</ldapSearchScope> * </sso-identity-store> * </pre> * <p/> * A sample LDAP Credential Store configuration : * <p/> * <pre> * <credential-store> * <class>org.josso.gateway.identity.service.store.ldap.LDAPIdentityStore</class> * <initialContextFactory>com.sun.jndi.ldap.LdapCtxFactory</initialContextFactory> * <providerUrl>ldap://localhost</providerUrl> * <securityPrincipal>cn=Manager\,dc=my-domain\,dc=com</securityPrincipal> * <securityCredential>secret</securityCredential> * <securityAuthentication>simple</securityAuthentication> * <usersCtxDN>ou=People\,dc=my-domain\,dc=com</usersCtxDN> * <principalUidAttributeID>uid</principalUidAttributeID> * <rolesCtxDN>ou=Roles\,dc=my-domain\,dc=com</rolesCtxDN> * <uidAttributeID>uniquemember</uidAttributeID> * <roleAttributeID>cn</roleAttributeID> * <credentialQueryString>uid=username\,userPassword=password</credentialQueryString> * <userPropertiesQueryString>mail=mail\,cn=description</userPropertiesQueryString> * </credential-store> * </pre> * * @author <a href="mailto:gbrigand@josso.org">Gianluca Brigandi</a> * @version CVS $Id: LDAPIdentityStore.java 1040 2009-03-05 00:56:52Z gbrigand $ * * @org.apache.xbean.XBean element="ldap-store" */ public class LDAPIdentityStore extends AbstractStore { private static final Log logger = LogFactory.getLog(LDAPIdentityStore.class); /** * Valid userPassword schemes according to RFC 2307 */ private static final String USERPASSWORD_SCHEME_MD5 = "{md5}"; private static final String USERPASSWORD_SCHEME_CRYPT = "{crypt}"; private static final String USERPASSWORD_SCHEME_SHA = "{sha}"; // ----------------------------------------------------- Instance Variables private String _initialContextFactory; private String _providerUrl; private String _securityAuthentication; private String _rolesCtxDN; private String _uidAttributeID; private String _roleAttributeID; private String _roleMatchingMode; private String _securityProtocol; private String _securityPrincipal; private String _securityCredential; private String _principalUidAttributeID; private String _usersCtxDN; private String _credentialQueryString; private String _userPropertiesQueryString; private String _ldapSearchScope; private String _updateableCredentialAttribute; // ----------------------------------------------------- Constructors public LDAPIdentityStore(){} // ----------------------------------------------------- IdentityStore Methods @Override public boolean userExists(UserKey key) throws SSOIdentityException { try { String dn = selectUserDN(((SimpleUserKey) key).getId()); return dn != null; } catch (NamingException e) { throw new SSOIdentityException(e); } } /** * Loads user information and its user attributes from the LDAP server. * * @param key the userid value to fetch the user in the LDAP server. * @return the user instance with the provided userid * @throws NoSuchUserException if the user does not exist * @throws SSOIdentityException a fatal exception loading the requested user */ public BaseUser loadUser(UserKey key) throws NoSuchUserException, SSOIdentityException { try { if (!(key instanceof SimpleUserKey)) { throw new SSOIdentityException("Unsupported key type : " + key.getClass().getName()); } String uid = selectUser(((SimpleUserKey) key).getId()); if (uid == null) throw new NoSuchUserException(key); BaseUser bu = new BaseUserImpl(); bu.setName(uid); List userProperties = new ArrayList(); // Optionally find user properties. if (getUserPropertiesQueryString() != null) { HashMap userPropertiesResultSet = selectUserProperties(((SimpleUserKey) key).getId()); Iterator i = userPropertiesResultSet.keySet().iterator(); while (i.hasNext()) { String pName = (String) i.next(); String pValue = (String) userPropertiesResultSet.get(pName); SSONameValuePair vp = new SSONameValuePair(pName, pValue); userProperties.add(vp); } } // Store User DN as a SSOUser property. String dn = selectUserDN(((SimpleUserKey) key).getId()); userProperties.add(new SSONameValuePair("josso.user.dn", dn)); SSONameValuePair[] props = (SSONameValuePair[]) userProperties.toArray(new SSONameValuePair[userProperties.size()]); bu.setProperties(props); return bu; } catch (NamingException e) { logger.error("NamingException while obtaining user", e); throw new SSOIdentityException("Error obtaining user : " + key); } } /** * Retrieves the roles for the supplied user. * * @param key the user id of the user for whom role information is to be retrieved. * @return the roles associated with the supplied user. * @throws SSOIdentityException fatal exception obtaining user roles. */ public BaseRole[] findRolesByUserKey(UserKey key) throws SSOIdentityException { try { if (!(key instanceof SimpleUserKey)) { throw new SSOIdentityException("Unsupported key type : " + key.getClass().getName()); } String[] roleNames = selectRolesByUsername(((SimpleUserKey) key).getId()); List roles = new ArrayList(); for (int i = 0; i < roleNames.length; i++) { String roleName = roleNames[i]; BaseRole role = new BaseRoleImpl(); role.setName(roleName); roles.add(role); } return (BaseRole[]) roles.toArray(new BaseRole[roles.size()]); } catch (NamingException e) { logger.error("NamingException while obtaining roles", e); throw new SSOIdentityException("Error obtaining roles for user : " + key); } } // ----------------------------------------------------- CredentialStore Methods /** * Loads user credential information for the supplied user from the LDAP server. * * @param key the user id of the user for whom credential information is to be retrieved. * @return the credentials associated with the supplied user. * @throws SSOIdentityException fatal exception obtaining user credentials */ public Credential[] loadCredentials(CredentialKey key, CredentialProvider cp) throws SSOIdentityException { try { if (!(key instanceof CredentialKey)) { throw new SSOIdentityException("Unsupported key type : " + key.getClass().getName()); } List credentials = new ArrayList(); HashMap credentialResultSet = selectCredentials(((SimpleUserKey) key).getId()); Iterator i = credentialResultSet.keySet().iterator(); while (i.hasNext()) { String cName = (String) i.next(); Object cValue = (Object) credentialResultSet.get(cName); Credential c = cp.newCredential(cName, cValue); credentials.add(c); } return (Credential[]) credentials.toArray(new Credential[credentialResultSet.size()]); } catch (NamingException e) { throw new SSOIdentityException("Error obtaining credentials for user : " + key + " ("+e.getMessage()+")", e); } } // ----------------------------------------------------- LDAP Primitives /** * Obtains the roles for the given user. * * @param username the user name to fetch user data. * @return the list of roles to which the user is associated to. * @throws NamingException LDAP error obtaining roles fro the given user */ protected String[] selectRolesByUsername(String username) throws NamingException, NoSuchUserException { List userRoles = new ArrayList(); InitialLdapContext ctx = createLdapInitialContext(); String rolesCtxDN = getRolesCtxDN(); // Search for any roles associated with the user if (rolesCtxDN != null) { // The attribute where user DN is stored in roles : String uidAttributeID = getUidAttributeID(); if (uidAttributeID == null) uidAttributeID = "uniquemember"; // The attribute that identifies the role name String roleAttrName = getRoleAttributeID(); if (roleAttrName == null) roleAttrName = "roles"; String userDN; if ("UID".equals(getRoleMatchingMode())) { // Use User ID to match the role userDN = username; } else if ("PRINCIPAL".equals(getRoleMatchingMode())) { // Use User ID to match the role userDN = _principalUidAttributeID + "=" + username; } else { // Default behaviour: Match the role using the User DN, not just the username : userDN = selectUserDN(username); } if (logger.isDebugEnabled()) logger.debug("Searching Roles for user '" + userDN + "' in Uid attribute name '" + uidAttributeID + "'"); if (userDN ==null) throw new NoSuchUserException(username); try { if (userDN.contains("\\")) { logger.debug("Escaping '\\' character"); userDN = userDN.replace("\\", "\\\\\\"); } NamingEnumeration answer = ctx.search(rolesCtxDN, "(&(" + uidAttributeID + "=" + userDN + "))", getSearchControls()); if (logger.isDebugEnabled()) logger.debug("Search Name: " + rolesCtxDN); if (logger.isDebugEnabled()) logger.debug("Search Filter: (&(" + uidAttributeID + "=" + userDN + "))"); if (!answer.hasMore()) logger.info("No roles found for user " + username); while (answer.hasMore()) { SearchResult sr = (SearchResult) answer.next(); Attributes attrs = sr.getAttributes(); Attribute roles = attrs.get(roleAttrName); for (int r = 0; r < roles.size(); r++) { Object value = roles.get(r); String roleName = null; // The role attribute value is the role name roleName = value.toString(); if (roleName != null) { if (logger.isDebugEnabled()) logger.debug("Saving role '" + roleName + "' for user '" + username + "'"); userRoles.add(roleName); } } } } catch (NamingException e) { if (logger.isDebugEnabled()) logger.debug("Failed to locate roles", e); } } // Close the context to release the connection ctx.close(); return (String[]) userRoles.toArray(new String[userRoles.size()]); } /** * Fetches the supplied user DN. * * @param uid the user id * @return the user DN for the supplied uid * @throws NamingException LDAP error obtaining user information. */ protected String selectUserDN(String uid) throws NamingException { String dn = null; InitialLdapContext ctx = createLdapInitialContext(); try { dn = selectUserDN(ctx, uid); } finally { // Close the context to release the connection ctx.close(); } return dn; } /** * Fetches the supplied user DN. * * @param uid the user id * @return the user DN for the supplied uid * @throws NamingException LDAP error obtaining user information. */ protected String selectUserDN(InitialLdapContext ctx, String uid) throws NamingException { String dn = null; String principalUidAttrName = this.getPrincipalUidAttributeID(); String usersCtxDN = this.getUsersCtxDN(); try { // NamingEnumeration answer = ctx.search(usersCtxDN, matchAttrs, principalAttr); // This gives more control over search behavior : NamingEnumeration answer = ctx.search(usersCtxDN, "(&(" + principalUidAttrName + "=" + uid + "))", getSearchControls()); while (answer.hasMore()) { SearchResult sr = (SearchResult) answer.next(); Attributes attrs = sr.getAttributes(); Attribute uidAttr = attrs.get(principalUidAttrName); if (uidAttr == null) { logger.warn("Invalid user uid attribute '" + principalUidAttrName + "'"); continue; } String uidValue = uidAttr.get().toString(); if (uidValue != null) { dn = sr.getName() + "," + usersCtxDN; if (logger.isDebugEnabled()) logger.debug("Found user '" + principalUidAttrName + "=" + uidValue + "' for user '" + uid + "' DN=" + dn); } else { if (logger.isDebugEnabled()) logger.debug("User not found for user '" + uid + "'"); } } } catch (NamingException e) { if (logger.isDebugEnabled()) logger.debug("Failed to locate user", e); } return dn; } protected String selectUser(String uid) throws NamingException { return selectUser( this.getPrincipalUidAttributeID(), uid ); } /** * Fetches the supplied user. * * @param attrValue the user id * @return the user id for the supplied uid * @throws NamingException LDAP error obtaining user information. */ protected String selectUser(String attrId, String attrValue ) throws NamingException { String uidValue = null; InitialLdapContext ctx = createLdapInitialContext(); String uidAttrName = this.getPrincipalUidAttributeID(); String usersCtxDN = this.getUsersCtxDN(); try { // NamingEnumeration answer = ctx.search(usersCtxDN, matchAttrs, principalAttr); // This gives more control over search behavior : NamingEnumeration answer = ctx.search(usersCtxDN, "(&(" + attrId + "=" + attrValue + "))", getSearchControls()); while (answer.hasMore()) { SearchResult sr = (SearchResult) answer.next(); Attributes attrs = sr.getAttributes(); Attribute uidAttr = attrs.get( uidAttrName ); if (uidAttr == null) { logger.warn("Invalid user attrValue attribute '" + uidAttrName + "'"); continue; } uidValue = uidAttr.get().toString(); if (uidValue != null) { if (logger.isDebugEnabled()) logger.debug("Found user '" + uidAttrName + "=" + uidValue + "' for user '" + attrValue + "'"); } else { if (logger.isDebugEnabled()) logger.debug("User not found for user '" + attrValue + "'"); } } } catch (NamingException e) { if (logger.isDebugEnabled()) logger.debug("Failed to locate user", e); } finally { // Close the context to release the connection ctx.close(); } return uidValue; } /** * Fetch the Ldap user attributes to be used as credentials. * * @param uid the user id for whom credentials are required * @return the hash map containing user credentials as name/value pairs * @throws NamingException LDAP error obtaining user credentials. */ protected HashMap selectCredentials(String uid) throws NamingException { HashMap credentialResultSet = new HashMap(); InitialLdapContext ctx = createLdapInitialContext(); String principalUidAttrName = this.getPrincipalUidAttributeID(); String usersCtxDN = this.getUsersCtxDN(); // BasicAttributes matchAttrs = new BasicAttributes(true); // matchAttrs.put(principalUidAttrName, uid); String credentialQueryString = getCredentialQueryString(); HashMap credentialQueryMap = parseQueryString(credentialQueryString); Iterator i = credentialQueryMap.keySet().iterator(); List credentialAttrList = new ArrayList(); while (i.hasNext()) { String o = (String) i.next(); credentialAttrList.add(o); } String[] credentialAttr = (String[]) credentialAttrList.toArray(new String[credentialAttrList.size()]); try { // NamingEnumeration answer = ctx.search(usersCtxDN, matchAttrs, credentialAttr); // This gives more control over search behavior : NamingEnumeration answer = ctx.search(usersCtxDN, "(&(" + principalUidAttrName + "=" + uid + "))", getSearchControls()); while (answer.hasMore()) { SearchResult sr = (SearchResult) answer.next(); Attributes attrs = sr.getAttributes(); for (int j = 0; j < credentialAttr.length; j++) { Object credentialObject = attrs.get(credentialAttr[j]).get(); String credentialName = (String) credentialQueryMap.get(credentialAttr[j]); String credentialValue = null; if (logger.isDebugEnabled()) logger.debug("Found user credential '" + credentialName + "' of type '" + credentialObject.getClass().getName() + "" + (credentialObject.getClass().isArray() ? "[" + Array.getLength(credentialObject) + "]" : "") + "'"); // if the attribute value is an array, cast it to byte[] and then convert to // String using proper encoding if (credentialObject.getClass().isArray()) { try { // Try to create a UTF-8 String, we use java.nio to handle errors in a better way. // If the byte[] cannot be converted to UTF-8, we're using the credentialObject as is. byte[] credentialData = (byte[]) credentialObject; ByteBuffer in = ByteBuffer.allocate(credentialData.length); in.put(credentialData); in.flip(); Charset charset = Charset.forName("UTF-8"); CharsetDecoder decoder = charset.newDecoder(); CharBuffer charBuffer = decoder.decode(in); credentialValue = charBuffer.toString(); } catch (CharacterCodingException e) { if (logger.isDebugEnabled()) logger.debug("Can't convert credential value to String using UTF-8"); } } else if (credentialObject instanceof String) { // The credential value must be a String ... credentialValue = (String) credentialObject; } // Check what do we have ... if (credentialValue != null) { // Remove any schema information from the credential value, like the {md5} prefix for passwords. credentialValue = getSchemeFreeValue(credentialValue); credentialResultSet.put(credentialName, credentialValue); } else { // We have a binary credential, leave it as it is ... probably binary value. credentialResultSet.put(credentialName, credentialObject); } if (logger.isDebugEnabled()) logger.debug("Found user credential '" + credentialName + "' with value '" + (credentialValue != null ? credentialValue : credentialObject) + "'"); } } } catch (NamingException e) { if (logger.isDebugEnabled()) logger.debug("Failed to locate user", e); } finally { // Close the context to release the connection ctx.close(); } return credentialResultSet; } /** * Obtain the properties for the user associated with the given uid using the * configured user properties query string. * * @param uid the user id of the user for whom its user properties are required. * @return the hash map containing user properties as name/value pairs. * @throws NamingException LDAP error obtaining user properties. */ protected HashMap selectUserProperties(String uid) throws NamingException { HashMap userPropertiesResultSet = new HashMap(); InitialLdapContext ctx = createLdapInitialContext(); BasicAttributes matchAttrs = new BasicAttributes(true); String principalUidAttrName = this.getPrincipalUidAttributeID(); String usersCtxDN = this.getUsersCtxDN(); matchAttrs.put(principalUidAttrName, uid); String userPropertiesQueryString = getUserPropertiesQueryString(); HashMap userPropertiesQueryMap = parseQueryString(userPropertiesQueryString); Iterator i = userPropertiesQueryMap.keySet().iterator(); List propertiesAttrList = new ArrayList(); while (i.hasNext()) { String o = (String) i.next(); propertiesAttrList.add(o); } String[] propertiesAttr = (String[]) propertiesAttrList.toArray( new String[propertiesAttrList.size()] ); try { // This gives more control over search behavior : NamingEnumeration answer = ctx.search(usersCtxDN, "(&(" + principalUidAttrName + "=" + uid + "))", getSearchControls()); while (answer.hasMore()) { SearchResult sr = (SearchResult) answer.next(); Attributes attrs = sr.getAttributes(); for (int j = 0; j < propertiesAttr.length; j++) { Attribute attribute = attrs.get(propertiesAttr[j]); if (attribute == null) { logger.warn("Invalid user property attribute '" + propertiesAttr[j] + "'"); continue; } Object propertyObject = attrs.get(propertiesAttr[j]).get(); if (propertyObject == null) { logger.warn("Found a 'null' value for user property '" + propertiesAttr[j] + "'"); continue; } String propertyValue = propertyObject.toString(); String propertyName = (String) userPropertiesQueryMap.get(propertiesAttr[j]); userPropertiesResultSet.put(propertyName, propertyValue); if (logger.isDebugEnabled()) logger.debug("Found user property '" + propertyName + "' with value '" + propertyValue + "'"); } } } catch (NamingException e) { if (logger.isDebugEnabled()) logger.debug("Failed to locate user", e); } finally { // Close the context to release the connection ctx.close(); } return userPropertiesResultSet; } protected void replaceAttributes(String bane, Attributes atts) throws NamingException { InitialLdapContext ctx = this.createLdapInitialContext( ); ctx.modifyAttributes( bane, InitialLdapContext.REPLACE_ATTRIBUTE, atts ); } /** * Creates an InitialLdapContext by logging into the configured Ldap Server using the configured * username and credential. * * @return the Initial Ldap Context to be used to perform searches, etc. * @throws NamingException LDAP binding error. */ protected InitialLdapContext createLdapInitialContext() throws NamingException { String securityPrincipal = getSecurityPrincipal(); if (securityPrincipal == null) securityPrincipal = ""; String securityCredential = getSecurityCredential(); if (securityCredential == null) securityCredential = ""; return createLdapInitialContext(securityPrincipal, securityCredential); } /** * Creates an InitialLdapContext by logging into the configured Ldap Server using the provided * username and credential. * * @return the Initial Ldap Context to be used to perform searches, etc. * @throws NamingException LDAP binding error. */ protected InitialLdapContext createLdapInitialContext(String securityPrincipal, String securityCredential) throws NamingException { Properties env = new Properties(); env.setProperty(Context.INITIAL_CONTEXT_FACTORY, getInitialContextFactory()); env.setProperty(Context.SECURITY_AUTHENTICATION, getSecurityAuthentication()); env.setProperty(Context.PROVIDER_URL, getProviderUrl()); env.setProperty(Context.SECURITY_PROTOCOL, (getSecurityProtocol() == null ? "" : getSecurityProtocol())); // Set defaults for key values if they are missing String factoryName = env.getProperty(Context.INITIAL_CONTEXT_FACTORY); if (factoryName == null) { factoryName = "com.sun.jndi.ldap.LdapCtxFactory"; env.setProperty(Context.INITIAL_CONTEXT_FACTORY, factoryName); } String authType = env.getProperty(Context.SECURITY_AUTHENTICATION); if (authType == null) env.setProperty(Context.SECURITY_AUTHENTICATION, "simple"); String protocol = env.getProperty(Context.SECURITY_PROTOCOL); String providerURL = getProviderUrl(); // Use localhost if providerUrl not set if (providerURL == null) { providerURL = "ldap://localhost:" + ((protocol != null && protocol.equals("ssl")) ? "636" : "389"); } else { // In case user configured provided URL if (providerURL.startsWith("ldaps")) { protocol = "ssl"; env.setProperty(Context.SECURITY_PROTOCOL, "ssl"); } } env.setProperty(Context.PROVIDER_URL, providerURL); if (securityPrincipal != null && !"".equals(securityPrincipal)) env.setProperty(Context.SECURITY_PRINCIPAL, securityPrincipal); if (securityCredential != null && !"".equals(securityCredential)) env.put(Context.SECURITY_CREDENTIALS, securityCredential); // always follow referrals transparently env.put(Context.REFERRAL, "follow"); // Logon into LDAP server if (logger.isDebugEnabled()) logger.debug("Logging into LDAP server, env=" + env); InitialLdapContext ctx = new InitialLdapContext(env, null); if (logger.isDebugEnabled()) logger.debug("Logged into LDAP server, " + ctx); return ctx; } /** * Returns the supplied attribute value without the scheme prefix. * This method should be invoked for 'userPassword' type attributes. * * @param attributeValue the attribute value * @return the scheme */ protected String getSchemeFreeValue(String attributeValue) { String targetValue = attributeValue; if (attributeValue.toLowerCase().startsWith(LDAPIdentityStore.USERPASSWORD_SCHEME_CRYPT)) { targetValue = attributeValue.substring(USERPASSWORD_SCHEME_CRYPT.length()); } else if (attributeValue.toLowerCase().startsWith(LDAPIdentityStore.USERPASSWORD_SCHEME_MD5)) { targetValue = attributeValue.substring(USERPASSWORD_SCHEME_MD5.length()); } else if (attributeValue.toLowerCase().startsWith(LDAPIdentityStore.USERPASSWORD_SCHEME_SHA)) { targetValue = attributeValue.substring(USERPASSWORD_SCHEME_SHA.length()); } return targetValue; } // ----------------------------------------------------- Utils /** * Parses a credential query string and builds a HashMap object * with key-value pairs. * The query string should be in the form of a string * and should have key-value pairs in the form <i>key=value</i>, * with each pair separated from the next by a ',' character. * * @param s a string containing the query to be parsed * @return a HashMap object built from the parsed key-value pairs * @throws IllegalArgumentException if the query string * is invalid */ protected HashMap parseQueryString(String s) { if (s == null) { throw new IllegalArgumentException(); } HashMap hm = new HashMap(); StringTokenizer st = new StringTokenizer(s, ","); while (st.hasMoreTokens()) { String pair = (String) st.nextToken(); int pos = pair.indexOf('='); if (pos == -1) { // XXX // should give more detail about the illegal argument throw new IllegalArgumentException(); } String key = pair.substring(0, pos); String val = pair.substring(pos + 1, pair.length()); hm.put(key, val); } return hm; } /** * This method returns the proper search controls to be used when querying the LDAP.. */ protected SearchControls getSearchControls() { SearchControls sc = new SearchControls(); sc.setSearchScope(_ldapSearchScope == null || _ldapSearchScope.equalsIgnoreCase("ONELEVEL") ? SearchControls.ONELEVEL_SCOPE : SearchControls.SUBTREE_SCOPE); return sc; } /** * Configuration Properties */ // ----------------------------------------------------- Configuration Properties public void setInitialContextFactory(String initialContextFactory) { _initialContextFactory = initialContextFactory; } public String getInitialContextFactory() { return _initialContextFactory; } public void setProviderUrl(String providerUrl) { _providerUrl = providerUrl; } public String getProviderUrl() { return _providerUrl; } public void setSecurityAuthentication(String securityAuthentication) { _securityAuthentication = securityAuthentication; } public String getSecurityAuthentication() { return _securityAuthentication; } public void setSecurityProtocol(String securityProtocol) { _securityProtocol = securityProtocol; } public String getSecurityProtocol() { return _securityProtocol; } public void setSecurityPrincipal(String securityPrincipal) { _securityPrincipal = securityPrincipal; } public String getSecurityPrincipal() { return _securityPrincipal; } public void setSecurityCredential(String securityCredential) { _securityCredential = securityCredential; } protected String getSecurityCredential() { return _securityCredential; } public String getLdapSearchScope() { return _ldapSearchScope; } public void setLdapSearchScope(String ldapSearchScope) { _ldapSearchScope = ldapSearchScope; } public void setUsersCtxDN(String usersCtxDN) { _usersCtxDN = usersCtxDN; } public String getUsersCtxDN() { return _usersCtxDN; } public void setRolesCtxDN(String rolesCtxDN) { _rolesCtxDN = rolesCtxDN; } public String getRolesCtxDN() { return _rolesCtxDN; } public void setPrincipalUidAttributeID(String principalUidAttributeID) { _principalUidAttributeID = principalUidAttributeID; } public String getPrincipalUidAttributeID() { return _principalUidAttributeID; } public void setUidAttributeID(String uidAttributeID) { _uidAttributeID = uidAttributeID; } public String getRoleMatchingMode() { return _roleMatchingMode; } public void setRoleMatchingMode(String roleMatchingMode) { this._roleMatchingMode = roleMatchingMode; } public String getUidAttributeID() { return _uidAttributeID; } public void setRoleAttributeID(String roleAttributeID) { _roleAttributeID = roleAttributeID; } public String getRoleAttributeID() { return _roleAttributeID; } public void setCredentialQueryString(String credentialQueryString) { _credentialQueryString = credentialQueryString; } public String getCredentialQueryString() { return _credentialQueryString; } public void setUserPropertiesQueryString(String userPropertiesQueryString) { _userPropertiesQueryString = userPropertiesQueryString; } public String getUserPropertiesQueryString() { return _userPropertiesQueryString; } public String getUpdateableCredentialAttribute () { return _updateableCredentialAttribute; } public void setUpdateableCredentialAttribute ( String updateableCredentialAttribute ) { this._updateableCredentialAttribute = updateableCredentialAttribute; } }