/* * Sun Public License * * The contents of this file are subject to the Sun Public License Version * 1.0 (the "License"). You may not use this file except in compliance with * the License. A copy of the License is available at http://www.sun.com/ * * The Original Code is the SLAMD Distributed Load Generation Engine. * The Initial Developer of the Original Code is Neil A. Wilson. * Portions created by Neil A. Wilson are Copyright (C) 2004-2010. * Some preexisting portions Copyright (C) 2002-2006 Sun Microsystems, Inc. * All Rights Reserved. * * Contributor(s): Neil A. Wilson */ package com.slamd.admin; import java.util.ArrayList; import java.util.HashMap; import netscape.ldap.LDAPAttribute; import netscape.ldap.LDAPConnection; import netscape.ldap.LDAPDN; import netscape.ldap.LDAPEntry; import netscape.ldap.LDAPException; import netscape.ldap.LDAPSearchResults; import netscape.ldap.LDAPUrl; import netscape.ldap.factory.JSSESocketFactory; import com.slamd.common.Constants; import com.slamd.jobs.JSSEBlindTrustSocketFactory; import com.slamd.server.SLAMDServer; /** * This class provides a mechanism for restricting access to components of the * administrative interface. It caches user access information for better * performance, but also provides a mechanism for flushing that cache so that * access can be re-evaluated. * * Note that this class does not actually restrict access or require * authentication, because that must be configured in the Web server itself. * Rather, this class will determine whether the authenticated user may access * a particular resource, as well as which resources a given user may access * (which are two different things). * * * @author Neil A. Wilson */ public class AccessManager { /** * The set of attributes to return if you don't want any attributes returned. */ private static final String[] noAttrs = new String[] { LDAPConnection.NO_ATTRS }; /** * The set of attributes to return if you want the member URL for a dynamic * group. */ private static final String[] memberURLAttrs = new String[] { Constants.MEMBER_URL_AT }; /** * The set of attributes to return if you want the list of roles from a user * entry. */ private static final String[] roleAttrs = new String[] { Constants.ROLE_DN_AT }; // Indicates whether the access manager has been stopped. private boolean managerStopped; // Indicates whether communication with the user directory should use SSL. private boolean useSSL; // Indicates whether the SLAMD server should blindly trust any certificate // presented by the user directory. private boolean userDirBlindTrust; // A cache of information about what a particular user may access. private HashMap<String,String[]> userInfoCache; // The port number for the user directory. private int userDirectoryPort; // The connection to the user directory. private LDAPConnection userDirConn; // The mutex used to provide threadsafe access to the user directory // connection. private final Object connMutex; // The mutex used to provide threadsafe access to the list of protected // resources. private final Object protectedResourceMutex; // The mutex used to provide threadsafe access to the user info cache. private final Object userCacheMutex; // The SLAMD server with which this access manager is associated. private SLAMDServer slamdServer; // The location of the JSSE key store. private String sslKeyStore; // The password for the JSSE key store. private String sslKeyPassword; // The location of the JSSE trust store. private String sslTrustStore; // The password for the JSSE trust store. private String sslTrustPassword; // The location in the user directory under which user accounts may be found. private String userBaseDN; // The DN to use to bind to the user directory. private String userDirectoryBindDN; // The password for the user directory bind DN. private String userDirectoryBindPW; // The hostname / IP address of the user directory. private String userDirectoryHost; // The name of the LDAP attribute used as the login ID. private String userIDAttribute; // The set of resources to which this access manager can protect access. private String[][] protectedResources; /** * Creates a new access manager to use for protecting access to the * administrative interface. Note that the manager will not be started, so * it is necessary to call the <CODE>startAccessMananager</CODE> to start it. * * @param userDirectoryHost The address of the user directory. * @param userDirectoryPort The port number of the user directory. * @param userDirectoryBindDN The DN to use to bind to the user directory. * @param userDirectoryBindPW The password for the user directory bind DN. * @param userBaseDN The location in the user directory under which * user entries may be found. * @param userIDAttribute The name of the LDAP attribute that is used as * the login ID. */ public AccessManager(String userDirectoryHost, int userDirectoryPort, String userDirectoryBindDN, String userDirectoryBindPW, String userBaseDN, String userIDAttribute) { this(userDirectoryHost, userDirectoryPort, userDirectoryBindDN, userDirectoryBindPW, userBaseDN, userIDAttribute, false, true, null, null, null, null); } /** * Creates a new access manager to use for protecting access to the * administrative interface. Note that the manager will not be started, so * it is necessary to call the <CODE>startAccessMananager</CODE> to start it. * * @param userDirectoryHost The address of the user directory. * @param userDirectoryPort The port number of the user directory. * @param userDirectoryBindDN The DN to use to bind to the user directory. * @param userDirectoryBindPW The password for the user directory bind DN. * @param userBaseDN The location in the user directory under which * user entries may be found. * @param userIDAttribute The name of the LDAP attribute that is used as * the login ID. * @param useSSL Indicates whether the communication with the * user directory should use SSL. * @param userDirBlindTrust Indicates whether the SLAMD server should * blindly trust any SSL certificate presented by * the user directory. * @param sslKeyStore The location of the JSSE key store to be used * for SSL communication. * @param sslKeyPassword The password to access the JSSE key store. * @param sslTrustStore The location of the JSSE trust store to be * used for SSL communication. * @param sslTrustPassword The password to access the JSSE trust store. */ public AccessManager(String userDirectoryHost, int userDirectoryPort, String userDirectoryBindDN, String userDirectoryBindPW, String userBaseDN, String userIDAttribute, boolean useSSL, boolean userDirBlindTrust, String sslKeyStore, String sslKeyPassword, String sslTrustStore, String sslTrustPassword) { // Set the values of the instance variables that correspond to constructor // arguments. this.userDirectoryHost = userDirectoryHost; this.userDirectoryPort = userDirectoryPort; this.userDirectoryBindDN = userDirectoryBindDN; this.userDirectoryBindPW = userDirectoryBindPW; this.userBaseDN = userBaseDN; this.userIDAttribute = userIDAttribute; this.useSSL = useSSL; this.userDirBlindTrust = userDirBlindTrust; this.sslKeyStore = sslKeyStore; this.sslKeyPassword = sslKeyPassword; this.sslTrustStore = sslTrustStore; this.sslTrustPassword = sslTrustPassword; // Initialize the remaining instance variables. this.managerStopped = true; this.connMutex = new Object(); this.protectedResourceMutex = new Object(); this.userCacheMutex = new Object(); this.userInfoCache = new HashMap<String,String[]>(); this.protectedResources = new String[0][]; } /** * Specifies the SLAMD server that should be associated with this access * manager. This is separate from the constructor because access to the admin * interface can be restricted even with the SLAMD server offline (e.g., to * restrict who can start and stop the server). Note that while the SLAMD * server is offline, certain functions like logging will not be performed. * * @param slamdServer The SLAMD server with which this access manager is * associated. */ void setSLAMDServer(SLAMDServer slamdServer) { this.slamdServer = slamdServer; logMessage("Associated the access manager with the SLAMD server"); } /** * Starts the access manager. If it is already running, then this does * nothing. Otherwise, it establishes the connection to the user directory * and configures recreates the user cache. * * @throws LDAPException If there is a problem establishing the connection * to the user directory. */ public void startAccessManager() throws LDAPException { logMessage("Starting the access manager"); // Grab all the locks synchronized (connMutex) { synchronized (protectedResourceMutex) { synchronized (userCacheMutex) { // Grab the connection to the user directory. if (useSSL) { if (userDirBlindTrust) { JSSEBlindTrustSocketFactory socketFactory = new JSSEBlindTrustSocketFactory(); userDirConn = new LDAPConnection(socketFactory); } else { if ((sslKeyStore != null) && (sslKeyStore.length() > 0)) { System.setProperty(Constants.SSL_KEY_STORE_PROPERTY, sslKeyStore); } if ((sslKeyPassword != null) && (sslKeyPassword.length() > 0)) { System.setProperty(Constants.SSL_KEY_PASSWORD_PROPERTY, sslKeyPassword); } if ((sslTrustStore != null) && (sslTrustStore.length() > 0)) { System.setProperty(Constants.SSL_TRUST_STORE_PROPERTY, sslTrustStore); } if ((sslTrustPassword != null) && (sslTrustPassword.length() > 0)) { System.setProperty(Constants.SSL_TRUST_PASSWORD_PROPERTY, sslTrustPassword); } userDirConn = new LDAPConnection(new JSSESocketFactory(null)); } } else { userDirConn = new LDAPConnection(); } userDirConn.connect(3, userDirectoryHost, userDirectoryPort, userDirectoryBindDN, userDirectoryBindPW); } } } managerStopped = false; logMessage("Access manager started"); } /** * Closes the connection to the user directory and stops the access manager. * Note that when the access manager is stopped, any requests to the access * manager will indicate that no access is allowed to anything. */ public void stopAccessManager() { logMessage("Stopping the access manager"); managerStopped = true; // Grab all the locks synchronized (connMutex) { synchronized (protectedResourceMutex) { synchronized (userCacheMutex) { // Close the connection to the user directory try { synchronized (connMutex) { userDirConn.disconnect(); } } catch (LDAPException le) { logMessage("Exception while closing the user directory " + "connection: " + le); } // Flush the user cache userInfoCache.clear(); } } } } /** * Indicates whether this access manager has been stopped. * * @return <CODE>true</CODE> if the access manager is stopped, or * <CODE>false</CODE> if it is running. */ public boolean managerIsStopped() { return managerStopped; } /** * Registers the specified resource as one that is protected by this access * manager. If the specified resource is already defined, then this will * assign it to the new resource DN. If specified, it will also flush the * user cache (which is necessary for users whose information is cached to be * able to access this new protected resource). * * @param resourceName The name associated with this protected resource. * @param resourceDN The DN of the entry in the user directory that will * be used to determine whether users may access this * resource. * @param flushUserCache Indicates whether the user cache should be flushed * in the process of adding this controlled resource. */ public void register(String resourceName, String resourceDN, boolean flushUserCache) { logMessage("In registerProtectedResource(" + resourceName + ", " + resourceDN + ", " + flushUserCache + ')'); resourceDN = LDAPDN.normalize(resourceDN.toLowerCase()); synchronized (protectedResourceMutex) { // If it's already there, then replace it. boolean added = false; for (int i=0; i < protectedResources.length; i++) { if (protectedResources[i][0].equals(resourceName)) { protectedResources[i][1] = resourceDN; added = true; break; } } // If it was not already in the list of protected resources, then add it. if (! added) { String[][] newResourceList = new String[protectedResources.length+1][]; System.arraycopy(protectedResources, 0, newResourceList, 0, protectedResources.length); newResourceList[protectedResources.length] = new String[] { resourceName, resourceDN }; protectedResources = newResourceList; } // Flush the user cache if appropriate. if (flushUserCache) { flushUserCache(); } } } /** * Removes the specified resource from the set of protected resources for this * access manager, optionally flushing the user cache in the process. * * @param resourceName The name of the protected resource to be * @param flushUserCache Indicates whether the user cache should be flushed * in the process of removing the controlled resource. */ public void deregister(String resourceName, boolean flushUserCache) { logMessage("In deregisterProtectedResource(" + resourceName + ", " + flushUserCache + ')'); synchronized (protectedResourceMutex) { // Iterate through the list. If the specified resource isn't in the list, // then there's no need to do anything. for (int i=0; i < protectedResources.length; i++) { if (protectedResources[i][0].equals(resourceName)) { String[][] newList = new String[protectedResources.length-1][]; System.arraycopy(protectedResources, 0, newList, 0, i); System.arraycopy(protectedResources, i+1, newList, i, newList.length-i); protectedResources = newList; // Flush the user cache if necessary. if (flushUserCache) { flushUserCache(); } return; } } } } /** * Retrieves the set of protected resources for this access manager. The * first element of each set will be the resource name and the second will be * the associated entry DN. * * @return The set of protected resources for this access manager. */ public String[][] getProtectedResources() { synchronized (protectedResourceMutex) { logMessage("getControlledResources() -- returning " + protectedResources.length + " items"); return protectedResources; } } /** * Flushes the user cache, which means that information about a user and what * he/she may access will be re-read from the user directory the next time the * user accesses a protected area of the administrative interface. */ public void flushUserCache() { logMessage("Flushing the user info cache"); synchronized (userCacheMutex) { userInfoCache.clear(); } } /** * Retrieves the names of all the protected resources that the specified user * may access. * * @param userIdentifier The ID of the user for which to retrieve the names * of the accessible resources. * * @return The names of all the protected resources that the specified user * may access. If no information is known about the specified user, * then <CODE>null</CODE> is returned. * * @throws AccessDeniedException If it is necessary to go to the user * directory to retrieve information for this * user but the user entry could not be found. * * @throws LDAPException If it is necessary to go to the user directory to * retrieve the information for this user and a * problem occurs while doing so. */ public String[] getAccessibleResources(String userIdentifier) throws AccessDeniedException, LDAPException { logMessage("In getAccessibleResources(" + userIdentifier + ')'); // If the access manager is stopped, then no access is granted to anyone. if (managerStopped) { logMessage("getAccessibleResources(" + userIdentifier + ") -- manager stopped; returning null"); } String[] accessibleResources = null; synchronized (userCacheMutex) { // First, check the user cache to see if we already have this information. accessibleResources = userInfoCache.get(userIdentifier); if (accessibleResources == null) { accessibleResources = getUserInfoFromDirectory(userIdentifier); if (accessibleResources != null) { userInfoCache.put(userIdentifier, accessibleResources); } } } return accessibleResources; } /** * Indicates whether the specified user may access the indicated resource. * * @param userIdentifier The ID of the user for which to make the * determination. * @param resourceName The name of the resource for which to check access * permissions. * * @return <CODE>true</CODE> if the user may access the indicated resource, * or <CODE>false</CODE> if not or if the manager is stopped. * * @throws AccessDeniedException If it is necessary to go to the user * directory to retrieve information for this * user but the user entry could not be found. * * @throws LDAPException If it is necessary to go to the user directory to * retrieve the information for this user and a * problem occurs while doing so. */ public boolean mayAccess(String userIdentifier, String resourceName) throws AccessDeniedException, LDAPException { // If the access manager is stopped, then no access is granted to anyone. if (managerStopped) { logMessage("mayAccess(" + userIdentifier + ", " + resourceName + ") -- manager stopped; returning false"); } String[] resources = getAccessibleResources(userIdentifier); if (resources == null) { logMessage("mayAccess(" + userIdentifier + ", " + resourceName + ") -- accessible resources is null; returning false"); return false; } for (int i=0; i < resources.length; i++) { if (resources[i].equals(resourceName)) { logMessage("mayAccess(" + userIdentifier + ", " + resourceName + ") returning true"); return true; } } logMessage("mayAccess(" + userIdentifier + ", " + resourceName + ") returning false"); return false; } /** * Retrieves the set of all accessible resources for the specified user from * the user directory. * * @param userIdentifier The identifier used to find the user entry in the * user directory. * * @return The names of all the resources that the user may access, or * <CODE>null</CODE> if the user could not be found in the * directory. * * @throws AccessDeniedException If the user entry could not be found in the * user directory. * * @throws LDAPException If there is a problem retrieving information from * the user directory. */ private String[] getUserInfoFromDirectory(String userIdentifier) throws AccessDeniedException, LDAPException { logMessage("In getUserInfoFromDirectory(" + userIdentifier + ')'); ArrayList<String> resourceList = new ArrayList<String>(); String[][] resources = getProtectedResources(); // First, retrieve the user entry from the directory. synchronized (connMutex) { String userDN = null; String filter = '(' + userIDAttribute + '=' + userIdentifier + ')'; LDAPSearchResults results = userDirConn.search(userBaseDN, LDAPConnection.SCOPE_SUB, filter, roleAttrs, false); while (results.hasMoreElements()) { Object element = results.nextElement(); if (element instanceof LDAPEntry) { // We have an entry, so first get the user's DN LDAPEntry entry = (LDAPEntry) element; userDN = LDAPDN.normalize(entry.getDN().toLowerCase()); // Next, check to see if this user is associated with any roles. LDAPAttribute attr = entry.getAttribute(Constants.ROLE_DN_AT); if (attr != null) { String[] values = attr.getStringValueArray(); if ((values != null) && (values.length > 0)) { for (int i=0; i < values.length; i++) { String roleDN = LDAPDN.normalize(values[i].toLowerCase()); for (int j=0; j < resources.length; j++) { if (roleDN.equals(resources[j][1])) { resourceList.add(resources[j][0]); logMessage(userIdentifier + " allowed for role resource " + resources[i][0]); break; } } } } } break; } } // If the user DN is null, then we couldn't find the user. if (userDN == null) { logMessage("Could not find user " + userIdentifier + " in directory"); throw new AccessDeniedException("Could not find user " + userIdentifier + " in the user directory"); } // Now look at the remaining resource DNs and see which apply to the user. for (int i=0; i < resources.length; i++) { // If the resource list already contains this resource name, then we // can go on to the next one. boolean matched = false; for (int j=0; j < resourceList.size(); j++) { if (resourceList.get(j).equals(resources[i][0])) { matched = true; break; } } // If we found a match in the resource list, then go to the next // protected resource. if (matched) { continue; } // See if this entry is a static group and the user is a member filter = "(|(&(objectclass=groupOfNames)(member=" + userDN + "))(&(objectclass=groupOfUniqueNames)(uniqueMember=" + userDN + ")))"; try { results = userDirConn.search(resources[i][1], LDAPConnection.SCOPE_BASE, filter, noAttrs, false); while (results.hasMoreElements()) { Object element = results.nextElement(); if (element instanceof LDAPEntry) { resourceList.add(resources[i][0]); logMessage(userIdentifier + " allowed for static group resource " + resources[i][0]); matched = true; break; } } } catch (LDAPException le) { if (le.getLDAPResultCode() == LDAPException.NO_SUCH_OBJECT) { // If we know the group entry doesn't exist, then there's no need // to try to retrieve it for dynamic groups either. logMessage("Resource DN entry " + resources[i][1] + " not found in the user directory"); continue; } else { throw le; } } // If we found a match as a static group, then go to the next protected // resource. if (matched) { continue; } // See if this entry is a dynamic group and the user matches the // criteria. filter = "(objectclass=groupOfURLs)"; results = userDirConn.search(resources[i][1], LDAPConnection.SCOPE_BASE, filter, memberURLAttrs, false); while (results.hasMoreElements()) { Object element = results.nextElement(); if (element instanceof LDAPEntry) { LDAPEntry entry = (LDAPEntry) element; LDAPAttribute attr = entry.getAttribute(Constants.MEMBER_URL_AT); if (attr != null) { String[] values = attr.getStringValueArray(); if ((values != null) && (values.length > 0)) { try { LDAPUrl url = new LDAPUrl(values[0]); String base = LDAPDN.normalize(url.getDN().toLowerCase()); if (userDN.endsWith(base)) { filter = url.getFilter(); LDAPSearchResults results2 = userDirConn.search(userDN, LDAPConnection.SCOPE_BASE, filter, noAttrs, false); while (results2.hasMoreElements()) { Object element2 = results2.nextElement(); if (element2 instanceof LDAPEntry) { resourceList.add(resources[i][0]); logMessage(userIdentifier + " allowed for dynamic " + "group resource " + resources[i][0]); break; } } } } catch (Exception e) {} } } break; } } } } // Finally, convert the resource list to an array and return it. String[] resourceArray = new String[resourceList.size()]; resourceList.toArray(resourceArray); return resourceArray; } /** * Attempts to authenticate the client based on the provided information. * * @param authID The authentication ID provided by the client. * @param authCredentials The credentials provided by the client. * @param msgBuffer The string buffer in which an explanation will be * placed in the event of a failure. * * @return The result code from the authentication process. */ public int authenticateClient(String authID, String authCredentials, StringBuilder msgBuffer) { synchronized (connMutex) { // First, find the user's entry in the directory. String filter = '(' + userIDAttribute + '=' + authID + ')'; LDAPSearchResults results; try { results = userDirConn.search(userBaseDN, LDAPConnection.SCOPE_SUB, filter, roleAttrs, false); } catch (LDAPException le) { msgBuffer.append("Unable to search user directory: " + le); return Constants.MESSAGE_RESPONSE_SERVER_ERROR; } LDAPEntry userEntry = null; while (results.hasMoreElements()) { Object element = results.nextElement(); if (element instanceof LDAPEntry) { if (userEntry == null) { userEntry = (LDAPEntry) element; } else { msgBuffer.append("Multiple entries found matching filter " + filter); return Constants.MESSAGE_RESPONSE_UNKNOWN_AUTH_ID; } } } if (userEntry == null) { msgBuffer.append("Unknown user \"" + authID + '"'); return Constants.MESSAGE_RESPONSE_UNKNOWN_AUTH_ID; } // Next, bind as the user to verify the credentials. String userDN = userEntry.getDN(); LDAPConnection bindConn; if (useSSL) { bindConn = new LDAPConnection(new JSSESocketFactory(null)); } else { bindConn = new LDAPConnection(); } try { bindConn.connect(userDirectoryHost, userDirectoryPort, userDN, authCredentials); } catch (LDAPException le) { try { bindConn.disconnect(); } catch (Exception e) {} int resultCode = le.getLDAPResultCode(); if (resultCode == LDAPException.INVALID_CREDENTIALS) { msgBuffer.append("Invalid credentials"); return Constants.MESSAGE_RESPONSE_INVALID_CREDENTIALS; } else { msgBuffer.append("Unable to verify user credentials: " + le); return Constants.MESSAGE_RESPONSE_SERVER_ERROR; } } try { bindConn.disconnect(); } catch (Exception e) {} // See if a group or role has been defined that specifies which clients // may authenticate. If so, then verify that the client is a member of // that group or role. String authDN = AdminServlet.resourceDNAuthenticateClient; if ((authDN != null) && (authDN.length() > 0)) { String normDN = LDAPDN.normalize(authDN); // First, check to see if the it is a role to which the user belongs. LDAPAttribute roleAttr = userEntry.getAttribute(Constants.ROLE_DN_AT); if (roleAttr != null) { String[] userRoles = roleAttr.getStringValueArray(); for (int i=0; ((userRoles != null) && (i < userRoles.length)); i++) { if (normDN.equalsIgnoreCase(LDAPDN.normalize(userRoles[i]))) { return Constants.MESSAGE_RESPONSE_SUCCESS; } } // See if this entry is a static group and the user is a member filter = "(|(&(objectclass=groupOfNames)(member=" + userDN + "))(&(objectclass=groupOfUniqueNames)(uniqueMember=" + userDN + ")))"; try { results = userDirConn.search(authDN, LDAPConnection.SCOPE_BASE, filter, noAttrs, false); while (results.hasMoreElements()) { Object element = results.nextElement(); if (element instanceof LDAPEntry) { return Constants.MESSAGE_RESPONSE_SUCCESS; } } } catch (LDAPException le) { if (le.getLDAPResultCode() == LDAPException.NO_SUCH_OBJECT) { // If we know the group entry doesn't exist, then there's no need // to try to retrieve it for dynamic groups either. msgBuffer.append("Resource DN \"" + authDN + "\" that specifies the clients that may " + "authenticate does not exist in the user " + "directory."); return Constants.MESSAGE_RESPONSE_CLIENT_REJECTED; } else { msgBuffer.append("Unable to search the user directory for " + "resource DN \"" + authDN + "\": " + le); return Constants.MESSAGE_RESPONSE_CLIENT_REJECTED; } } // See if the DN is a dynamic group and if so whether the user is a // member. String memberURL = null; filter = "(objectClass=groupOfURLs)"; try { results = userDirConn.search(authDN, LDAPConnection.SCOPE_BASE, filter, memberURLAttrs, false); while (results.hasMoreElements()) { Object element = results.nextElement(); if (element instanceof LDAPEntry) { LDAPEntry entry = (LDAPEntry) element; LDAPAttribute urlAttr = entry.getAttribute(Constants.MEMBER_URL_AT); if (urlAttr == null) { msgBuffer.append("Unable to verify user \"" + authID + "\" as a member of \"" + authDN + '"'); return Constants.MESSAGE_RESPONSE_CLIENT_REJECTED; } String[] values = urlAttr.getStringValueArray(); if ((values == null) || (values.length != 1)) { msgBuffer.append("Unable to verify user \"" + authID + "\" as a member of \"" + authDN + '"'); return Constants.MESSAGE_RESPONSE_CLIENT_REJECTED; } memberURL = values[0]; break; } } } catch (LDAPException le) { msgBuffer.append("Unable to search the user directory for " + "resource DN \"" + authDN + "\": " + le); return Constants.MESSAGE_RESPONSE_CLIENT_REJECTED; } if (memberURL == null) { msgBuffer.append("Unable to verify user \"" + authID + "\" as a member of \"" + authDN + '"'); return Constants.MESSAGE_RESPONSE_CLIENT_REJECTED; } try { LDAPUrl url = new LDAPUrl(memberURL); String base = LDAPDN.normalize(url.getDN().toLowerCase()); userDN = LDAPDN.normalize(userDN); if (userDN.endsWith(base)) { filter = url.getFilter(); LDAPSearchResults results2 = userDirConn.search(userDN, LDAPConnection.SCOPE_BASE, filter, noAttrs, false); while (results2.hasMoreElements()) { Object element2 = results2.nextElement(); if (element2 instanceof LDAPEntry) { return Constants.MESSAGE_RESPONSE_SUCCESS; } } } } catch (Exception e) { msgBuffer.append("Unable to verify user \"" + authID + "\" as a member of \"" + authDN + "\" -- " + e); return Constants.MESSAGE_RESPONSE_CLIENT_REJECTED; } } msgBuffer.append("User \"" + authID + "\" is not authorized to " + "connect to the SLAMD server as a client."); return Constants.MESSAGE_RESPONSE_CLIENT_REJECTED; } return Constants.MESSAGE_RESPONSE_SUCCESS; } } /** * Logs the specified message to the SLAMD log file using the access manager * debugging log level. Note that if the SLAMD server is not specified, then * the message will not be logged. * * @param message The message to write to the SLAMD log. */ private void logMessage(String message) { if (slamdServer != null) { slamdServer.logMessage(Constants.LOG_LEVEL_ACCESS_MANAGER_DEBUG, message); } } }