GUACAMOLE-957: Refactor LDAP configuration such that it may be user-specific.

This commit is contained in:
Michael Jumper
2021-10-20 18:45:06 -07:00
parent a06802c320
commit 07b443257f
11 changed files with 738 additions and 515 deletions

View File

@@ -35,6 +35,7 @@ import org.apache.directory.ldap.client.api.LdapNetworkConnection;
import org.apache.guacamole.GuacamoleException; import org.apache.guacamole.GuacamoleException;
import org.apache.guacamole.GuacamoleServerException; import org.apache.guacamole.GuacamoleServerException;
import org.apache.guacamole.auth.ldap.conf.ConfigurationService; import org.apache.guacamole.auth.ldap.conf.ConfigurationService;
import org.apache.guacamole.auth.ldap.conf.LDAPConfiguration;
import org.apache.guacamole.auth.ldap.group.UserGroupService; import org.apache.guacamole.auth.ldap.group.UserGroupService;
import org.apache.guacamole.auth.ldap.user.LDAPAuthenticatedUser; import org.apache.guacamole.auth.ldap.user.LDAPAuthenticatedUser;
import org.apache.guacamole.auth.ldap.user.LDAPUserContext; import org.apache.guacamole.auth.ldap.user.LDAPUserContext;
@@ -105,6 +106,9 @@ public class AuthenticationProviderService {
* or queried from the LDAP server, depending on how LDAP authentication * or queried from the LDAP server, depending on how LDAP authentication
* has been configured. * has been configured.
* *
* @param config
* The configuration of the LDAP server being queried.
*
* @param username * @param username
* The username of the user whose corresponding DN should be returned. * The username of the user whose corresponding DN should be returned.
* *
@@ -115,18 +119,17 @@ public class AuthenticationProviderService {
* If required properties are missing, and thus the user DN cannot be * If required properties are missing, and thus the user DN cannot be
* determined. * determined.
*/ */
private Dn getUserBindDN(String username) throws GuacamoleException { private Dn getUserBindDN(LDAPConfiguration config, String username)
throws GuacamoleException {
// If a search DN is provided, search the LDAP directory for the DN // If a search DN is provided, search the LDAP directory for the DN
// corresponding to the given username // corresponding to the given username
String searchBindLogon = confService.getSearchBindDN(); String searchBindLogon = config.getSearchBindDN();
if (searchBindLogon != null) { if (searchBindLogon != null) {
// Create an LDAP connection using the search account // Create an LDAP connection using the search account
LdapNetworkConnection searchConnection = ldapService.bindAs( LdapNetworkConnection searchConnection = ldapService.bindAs(config,
searchBindLogon, searchBindLogon, config.getSearchBindPassword());
confService.getSearchBindPassword()
);
// Warn of failure to find // Warn of failure to find
if (searchConnection == null) { if (searchConnection == null) {
@@ -138,7 +141,7 @@ public class AuthenticationProviderService {
try { try {
// Retrieve all DNs associated with the given username // Retrieve all DNs associated with the given username
List<Dn> userDNs = userService.getUserDNs(searchConnection, username); List<Dn> userDNs = userService.getUserDNs(config, searchConnection, username);
if (userDNs.isEmpty()) if (userDNs.isEmpty())
return null; return null;
@@ -161,7 +164,7 @@ public class AuthenticationProviderService {
} }
// Otherwise, derive user DN from base DN // Otherwise, derive user DN from base DN
return userService.deriveUserDN(username); return userService.deriveUserDN(config, username);
} }
@@ -197,7 +200,14 @@ public class AuthenticationProviderService {
+ " authentication provider.", CredentialsInfo.USERNAME_PASSWORD); + " authentication provider.", CredentialsInfo.USERNAME_PASSWORD);
} }
Dn bindDn = getUserBindDN(username); // Get relevant LDAP configuration for user
LDAPConfiguration config = confService.getLDAPConfiguration(username);
if (config == null) {
throw new GuacamoleInvalidCredentialsException("User \"" + username + "\" "
+ "does not map to any defined LDAP configuration.", CredentialsInfo.USERNAME_PASSWORD);
}
Dn bindDn = getUserBindDN(config, username);
if (bindDn == null || bindDn.isEmpty()) { if (bindDn == null || bindDn.isEmpty()) {
throw new GuacamoleInvalidCredentialsException("Unable to determine" throw new GuacamoleInvalidCredentialsException("Unable to determine"
+ " DN of user " + username, CredentialsInfo.USERNAME_PASSWORD); + " DN of user " + username, CredentialsInfo.USERNAME_PASSWORD);
@@ -205,7 +215,7 @@ public class AuthenticationProviderService {
// Attempt bind // Attempt bind
LdapNetworkConnection ldapConnection = LdapNetworkConnection ldapConnection =
ldapService.bindAs(bindDn.getName(), password); ldapService.bindAs(config, bindDn.getName(), password);
if (ldapConnection == null) if (ldapConnection == null)
throw new GuacamoleInvalidCredentialsException("Invalid login.", throw new GuacamoleInvalidCredentialsException("Invalid login.",
CredentialsInfo.USERNAME_PASSWORD); CredentialsInfo.USERNAME_PASSWORD);
@@ -214,13 +224,14 @@ public class AuthenticationProviderService {
// Retrieve group membership of the user that just authenticated // Retrieve group membership of the user that just authenticated
Set<String> effectiveGroups = Set<String> effectiveGroups =
userGroupService.getParentUserGroupIdentifiers(ldapConnection, userGroupService.getParentUserGroupIdentifiers(config,
bindDn); ldapConnection, bindDn);
// Return AuthenticatedUser if bind succeeds // Return AuthenticatedUser if bind succeeds
LDAPAuthenticatedUser authenticatedUser = authenticatedUserProvider.get(); LDAPAuthenticatedUser authenticatedUser = authenticatedUserProvider.get();
authenticatedUser.init(credentials, getAttributeTokens(ldapConnection, authenticatedUser.init(config, credentials,
bindDn), effectiveGroups, bindDn); getAttributeTokens(config, ldapConnection, bindDn),
effectiveGroups, bindDn);
return authenticatedUser; return authenticatedUser;
@@ -240,6 +251,9 @@ public class AuthenticationProviderService {
* guacamole.properties. If no attributes are specified or none are * guacamole.properties. If no attributes are specified or none are
* found on the LDAP user object, an empty map is returned. * found on the LDAP user object, an empty map is returned.
* *
* @param config
* The configuration of the LDAP server being queried.
*
* @param ldapConnection * @param ldapConnection
* LDAP connection to use to read the attributes of the user. * LDAP connection to use to read the attributes of the user.
* *
@@ -255,11 +269,11 @@ public class AuthenticationProviderService {
* @throws GuacamoleException * @throws GuacamoleException
* If an error occurs retrieving the user DN or the attributes. * If an error occurs retrieving the user DN or the attributes.
*/ */
private Map<String, String> getAttributeTokens(LdapNetworkConnection ldapConnection, private Map<String, String> getAttributeTokens(LDAPConfiguration config,
Dn userDn) throws GuacamoleException { LdapNetworkConnection ldapConnection, Dn userDn) throws GuacamoleException {
// Get attributes from configuration information // Get attributes from configuration information
List<String> attrList = confService.getAttributes(); List<String> attrList = config.getAttributes();
// If there are no attributes there is no reason to search LDAP // If there are no attributes there is no reason to search LDAP
if (attrList.isEmpty()) if (attrList.isEmpty())
@@ -316,9 +330,11 @@ public class AuthenticationProviderService {
Credentials credentials = authenticatedUser.getCredentials(); Credentials credentials = authenticatedUser.getCredentials();
if (authenticatedUser instanceof LDAPAuthenticatedUser) { if (authenticatedUser instanceof LDAPAuthenticatedUser) {
Dn bindDn = ((LDAPAuthenticatedUser) authenticatedUser).getBindDn(); LDAPAuthenticatedUser ldapAuthenticatedUser = (LDAPAuthenticatedUser) authenticatedUser;
LdapNetworkConnection ldapConnection = LDAPConfiguration config = ldapAuthenticatedUser.getLDAPConfiguration();
ldapService.bindAs(bindDn.getName(), credentials.getPassword()); Dn bindDn = ldapAuthenticatedUser.getBindDn();
LdapNetworkConnection ldapConnection = ldapService.bindAs(config, bindDn.getName(), credentials.getPassword());
if (ldapConnection == null) { if (ldapConnection == null) {
logger.debug("LDAP bind succeeded for \"{}\" during " logger.debug("LDAP bind succeeded for \"{}\" during "
+ "authentication but failed during data retrieval.", + "authentication but failed during data retrieval.",
@@ -331,7 +347,7 @@ public class AuthenticationProviderService {
// Build user context by querying LDAP // Build user context by querying LDAP
LDAPUserContext userContext = userContextProvider.get(); LDAPUserContext userContext = userContextProvider.get();
userContext.init(authenticatedUser, ldapConnection); userContext.init(ldapAuthenticatedUser, ldapConnection);
return userContext; return userContext;
} }

View File

@@ -19,7 +19,6 @@
package org.apache.guacamole.auth.ldap; package org.apache.guacamole.auth.ldap;
import com.google.inject.Inject;
import org.apache.directory.api.ldap.model.exception.LdapAuthenticationException; import org.apache.directory.api.ldap.model.exception.LdapAuthenticationException;
import org.apache.directory.api.ldap.model.exception.LdapException; import org.apache.directory.api.ldap.model.exception.LdapException;
import org.apache.directory.api.ldap.model.exception.LdapInvalidDnException; import org.apache.directory.api.ldap.model.exception.LdapInvalidDnException;
@@ -34,8 +33,8 @@ import org.apache.directory.ldap.client.api.LdapNetworkConnection;
import org.apache.guacamole.GuacamoleException; import org.apache.guacamole.GuacamoleException;
import org.apache.guacamole.GuacamoleServerException; import org.apache.guacamole.GuacamoleServerException;
import org.apache.guacamole.GuacamoleUnsupportedException; import org.apache.guacamole.GuacamoleUnsupportedException;
import org.apache.guacamole.auth.ldap.conf.ConfigurationService;
import org.apache.guacamole.auth.ldap.conf.EncryptionMethod; import org.apache.guacamole.auth.ldap.conf.EncryptionMethod;
import org.apache.guacamole.auth.ldap.conf.LDAPConfiguration;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@@ -49,12 +48,6 @@ public class LDAPConnectionService {
*/ */
private static final Logger logger = LoggerFactory.getLogger(LDAPConnectionService.class); private static final Logger logger = LoggerFactory.getLogger(LDAPConnectionService.class);
/**
* Service for retrieving LDAP server configuration information.
*/
@Inject
private ConfigurationService confService;
/** /**
* Creates a new instance of LdapNetworkConnection, configured as required * Creates a new instance of LdapNetworkConnection, configured as required
* to use the given encryption method to communicate with the LDAP server * to use the given encryption method to communicate with the LDAP server
@@ -130,6 +123,9 @@ public class LDAPConnectionService {
* requested, and will not be connected until it is used in an LDAP * requested, and will not be connected until it is used in an LDAP
* operation (such as a bind). * operation (such as a bind).
* *
* @param config
* The configuration of the LDAP server being queried.
*
* @return * @return
* A new LdapNetworkConnection instance which has already been * A new LdapNetworkConnection instance which has already been
* configured to use the encryption method, hostname, and port * configured to use the encryption method, hostname, and port
@@ -139,12 +135,12 @@ public class LDAPConnectionService {
* If an error occurs while parsing guacamole.properties, or if the * If an error occurs while parsing guacamole.properties, or if the
* requested encryption method is actually not implemented (a bug). * requested encryption method is actually not implemented (a bug).
*/ */
private LdapNetworkConnection createLDAPConnection() private LdapNetworkConnection createLDAPConnection(LDAPConfiguration config)
throws GuacamoleException { throws GuacamoleException {
return createLDAPConnection( return createLDAPConnection(
confService.getServerHostname(), config.getServerHostname(),
confService.getServerPort(), config.getServerPort(),
confService.getEncryptionMethod()); config.getEncryptionMethod());
} }
/** /**
@@ -156,6 +152,9 @@ public class LDAPConnectionService {
* requested, and will not be connected until it is used in an LDAP * requested, and will not be connected until it is used in an LDAP
* operation (such as a bind). * operation (such as a bind).
* *
* @param config
* The configuration of the LDAP server being queried.
*
* @param url * @param url
* The LDAP URL containing the details which should be used to connect * The LDAP URL containing the details which should be used to connect
* to the LDAP server. * to the LDAP server.
@@ -170,8 +169,8 @@ public class LDAPConnectionService {
* method indicated by the URL is known but not actually implemented (a * method indicated by the URL is known but not actually implemented (a
* bug). * bug).
*/ */
private LdapNetworkConnection createLDAPConnection(String url) private LdapNetworkConnection createLDAPConnection(LDAPConfiguration config,
throws GuacamoleException { String url) throws GuacamoleException {
// Parse provided LDAP URL // Parse provided LDAP URL
LdapUrl ldapUrl; LdapUrl ldapUrl;
@@ -197,7 +196,7 @@ public class LDAPConnectionService {
// Use STARTTLS for otherwise unencrypted ldap:// URLs if the main // Use STARTTLS for otherwise unencrypted ldap:// URLs if the main
// LDAP connection requires STARTTLS // LDAP connection requires STARTTLS
else if (confService.getEncryptionMethod() == EncryptionMethod.STARTTLS) { else if (config.getEncryptionMethod() == EncryptionMethod.STARTTLS) {
logger.debug("Using STARTTLS for LDAP URL \"{}\" as the main LDAP " logger.debug("Using STARTTLS for LDAP URL \"{}\" as the main LDAP "
+ "connection described in guacamole.properties is " + "connection described in guacamole.properties is "
+ "configured to use STARTTLS.", url); + "configured to use STARTTLS.", url);
@@ -329,6 +328,9 @@ public class LDAPConnectionService {
* hostname, port, and encryption method of the LDAP server are determined * hostname, port, and encryption method of the LDAP server are determined
* from guacamole.properties. * from guacamole.properties.
* *
* @param config
* The configuration of the LDAP server being queried.
*
* @param bindUser * @param bindUser
* The DN or UPN of the user to bind as, or null to bind anonymously. * The DN or UPN of the user to bind as, or null to bind anonymously.
* *
@@ -344,15 +346,18 @@ public class LDAPConnectionService {
* If an error occurs while parsing guacamole.properties, or if the * If an error occurs while parsing guacamole.properties, or if the
* configured encryption method is actually not implemented (a bug). * configured encryption method is actually not implemented (a bug).
*/ */
public LdapNetworkConnection bindAs(String bindUser, String password) public LdapNetworkConnection bindAs(LDAPConfiguration config,
throws GuacamoleException { String bindUser, String password) throws GuacamoleException {
return bindAs(createLDAPConnection(), bindUser, password); return bindAs(createLDAPConnection(config), bindUser, password);
} }
/** /**
* Binds to the LDAP server indicated by the given LDAP URL using the * Binds to the LDAP server indicated by the given LDAP URL using the
* credentials that were used to bind an existing LdapNetworkConnection. * credentials that were used to bind an existing LdapNetworkConnection.
* *
* @param config
* The configuration of the LDAP server being queried.
*
* @param url * @param url
* The LDAP URL containing the details which should be used to connect * The LDAP URL containing the details which should be used to connect
* to the LDAP server. * to the LDAP server.
@@ -370,16 +375,19 @@ public class LDAPConnectionService {
* method indicated by the URL is known but not actually implemented (a * method indicated by the URL is known but not actually implemented (a
* bug). * bug).
*/ */
public LdapNetworkConnection bindAs(String url, public LdapNetworkConnection bindAs(LDAPConfiguration config, String url,
LdapNetworkConnection useCredentialsFrom) LdapNetworkConnection useCredentialsFrom)
throws GuacamoleException { throws GuacamoleException {
return bindAs(createLDAPConnection(url), useCredentialsFrom); return bindAs(createLDAPConnection(config, url), useCredentialsFrom);
} }
/** /**
* Generate a SearchRequest object using the given Base DN and filter * Generate a SearchRequest object using the given Base DN and filter
* and retrieving other properties from the LDAP configuration service. * and retrieving other properties from the LDAP configuration service.
* *
* @param config
* The configuration of the LDAP server being queried.
*
* @param baseDn * @param baseDn
* The LDAP Base DN at which to search the search. * The LDAP Base DN at which to search the search.
* *
@@ -392,19 +400,19 @@ public class LDAPConnectionService {
* @throws GuacamoleException * @throws GuacamoleException
* If an error occurs retrieving any of the configuration values. * If an error occurs retrieving any of the configuration values.
*/ */
public SearchRequest getSearchRequest(Dn baseDn, ExprNode filter) public SearchRequest getSearchRequest(LDAPConfiguration config, Dn baseDn,
throws GuacamoleException { ExprNode filter) throws GuacamoleException {
SearchRequest searchRequest = new SearchRequestImpl(); SearchRequest searchRequest = new SearchRequestImpl();
searchRequest.setBase(baseDn); searchRequest.setBase(baseDn);
searchRequest.setDerefAliases(confService.getDereferenceAliases()); searchRequest.setDerefAliases(config.getDereferenceAliases());
searchRequest.setScope(SearchScope.SUBTREE); searchRequest.setScope(SearchScope.SUBTREE);
searchRequest.setFilter(filter); searchRequest.setFilter(filter);
searchRequest.setSizeLimit(confService.getMaxResults()); searchRequest.setSizeLimit(config.getMaxResults());
searchRequest.setTimeLimit(confService.getOperationTimeout()); searchRequest.setTimeLimit(config.getOperationTimeout());
searchRequest.setTypesOnly(false); searchRequest.setTypesOnly(false);
if (confService.getFollowReferrals()) if (config.getFollowReferrals())
searchRequest.followReferrals(); searchRequest.followReferrals();
return searchRequest; return searchRequest;

View File

@@ -44,7 +44,7 @@ import org.apache.directory.api.ldap.model.name.Dn;
import org.apache.directory.ldap.client.api.LdapNetworkConnection; import org.apache.directory.ldap.client.api.LdapNetworkConnection;
import org.apache.guacamole.GuacamoleException; import org.apache.guacamole.GuacamoleException;
import org.apache.guacamole.GuacamoleServerException; import org.apache.guacamole.GuacamoleServerException;
import org.apache.guacamole.auth.ldap.conf.ConfigurationService; import org.apache.guacamole.auth.ldap.conf.LDAPConfiguration;
import org.apache.guacamole.auth.ldap.conf.LDAPGuacamoleProperties; import org.apache.guacamole.auth.ldap.conf.LDAPGuacamoleProperties;
import org.apache.guacamole.net.auth.Identifiable; import org.apache.guacamole.net.auth.Identifiable;
import org.slf4j.Logger; import org.slf4j.Logger;
@@ -70,12 +70,6 @@ public class ObjectQueryService {
@Inject @Inject
private LDAPConnectionService ldapService; private LDAPConnectionService ldapService;
/**
* Service for retrieving LDAP server configuration information.
*/
@Inject
private ConfigurationService confService;
/** /**
* Returns the identifier of the object represented by the given LDAP * Returns the identifier of the object represented by the given LDAP
* entry. Multiple attributes may be declared as containing the identifier * entry. Multiple attributes may be declared as containing the identifier
@@ -184,6 +178,9 @@ public class ObjectQueryService {
* list of all results. Only objects beneath the given base DN are * list of all results. Only objects beneath the given base DN are
* included in the search. * included in the search.
* *
* @param config
* The configuration of the LDAP server being queried.
*
* @param ldapConnection * @param ldapConnection
* The current connection to the LDAP server, associated with the * The current connection to the LDAP server, associated with the
* current user. * current user.
@@ -212,12 +209,13 @@ public class ObjectQueryService {
* information required to execute the query cannot be read from * information required to execute the query cannot be read from
* guacamole.properties. * guacamole.properties.
*/ */
public List<Entry> search(LdapNetworkConnection ldapConnection, public List<Entry> search(LDAPConfiguration config,
Dn baseDN, ExprNode query, int searchHop, LdapNetworkConnection ldapConnection, Dn baseDN, ExprNode query,
Collection<String> attributes) throws GuacamoleException { int searchHop, Collection<String> attributes)
throws GuacamoleException {
// Refuse to follow referrals if limit has been reached // Refuse to follow referrals if limit has been reached
int maxHops = confService.getMaxReferralHops(); int maxHops = config.getMaxReferralHops();
if (searchHop >= maxHops) { if (searchHop >= maxHops) {
logger.debug("Refusing to follow further referrals as the maximum " logger.debug("Refusing to follow further referrals as the maximum "
+ "number of referral hops ({}) has been reached. LDAP " + "number of referral hops ({}) has been reached. LDAP "
@@ -230,8 +228,7 @@ public class ObjectQueryService {
logger.debug("Searching \"{}\" for objects matching \"{}\".", baseDN, query); logger.debug("Searching \"{}\" for objects matching \"{}\".", baseDN, query);
// Search within subtree of given base DN // Search within subtree of given base DN
SearchRequest request = ldapService.getSearchRequest(baseDN, query); SearchRequest request = ldapService.getSearchRequest(config, baseDN, query);
if (attributes != null) if (attributes != null)
request.addAttributes(attributes.toArray(new String[0])); request.addAttributes(attributes.toArray(new String[0]));
@@ -257,10 +254,10 @@ public class ObjectQueryService {
// Connect to referred LDAP server to retrieve further results, ensuring the network // Connect to referred LDAP server to retrieve further results, ensuring the network
// connection is always closed when it will no longer be used // connection is always closed when it will no longer be used
try (LdapNetworkConnection referralConnection = ldapService.bindAs(url, ldapConnection)) { try (LdapNetworkConnection referralConnection = ldapService.bindAs(config, url, ldapConnection)) {
if (referralConnection != null) { if (referralConnection != null) {
logger.debug("Following referral to \"{}\"...", url); logger.debug("Following referral to \"{}\"...", url);
entries.addAll(search(referralConnection, baseDN, query, searchHop + 1, attributes)); entries.addAll(search(config, referralConnection, baseDN, query, searchHop + 1, attributes));
} }
else else
logger.debug("Could not bind with LDAP " logger.debug("Could not bind with LDAP "
@@ -304,6 +301,9 @@ public class ObjectQueryService {
* given connection, returning a list of all results. Only objects beneath * given connection, returning a list of all results. Only objects beneath
* the given base DN are included in the search. * the given base DN are included in the search.
* *
* @param config
* The configuration of the LDAP server being queried.
*
* @param ldapConnection * @param ldapConnection
* The current connection to the LDAP server, associated with the * The current connection to the LDAP server, associated with the
* current user. * current user.
@@ -339,12 +339,12 @@ public class ObjectQueryService {
* information required to execute the query cannot be read from * information required to execute the query cannot be read from
* guacamole.properties. * guacamole.properties.
*/ */
public List<Entry> search(LdapNetworkConnection ldapConnection, Dn baseDN, public List<Entry> search(LDAPConfiguration config,
ExprNode filter, Collection<String> filterAttributes, String filterValue, LdapNetworkConnection ldapConnection, Dn baseDN, ExprNode filter,
Collection<String> attributes) Collection<String> filterAttributes, String filterValue,
throws GuacamoleException { Collection<String> attributes) throws GuacamoleException {
ExprNode query = generateQuery(filter, filterAttributes, filterValue); ExprNode query = generateQuery(filter, filterAttributes, filterValue);
return search(ldapConnection, baseDN, query, 0, attributes); return search(config, ldapConnection, baseDN, query, 0, attributes);
} }
/** /**

View File

@@ -20,12 +20,6 @@
package org.apache.guacamole.auth.ldap.conf; package org.apache.guacamole.auth.ldap.conf;
import com.google.inject.Inject; import com.google.inject.Inject;
import java.util.Collections;
import java.util.List;
import org.apache.directory.api.ldap.model.filter.ExprNode;
import org.apache.directory.api.ldap.model.filter.PresenceNode;
import org.apache.directory.api.ldap.model.message.AliasDerefMode;
import org.apache.directory.api.ldap.model.name.Dn;
import org.apache.guacamole.GuacamoleException; import org.apache.guacamole.GuacamoleException;
import org.apache.guacamole.environment.Environment; import org.apache.guacamole.environment.Environment;
@@ -41,375 +35,24 @@ public class ConfigurationService {
private Environment environment; private Environment environment;
/** /**
* Returns the hostname of the LDAP server as configured with * Returns the configuration information for the LDAP server related to the
* guacamole.properties. By default, this will be "localhost". * user having the given username. If no such LDAP server is defined, null
*
* @return
* The hostname of the LDAP server, as configured with
* guacamole.properties.
*
* @throws GuacamoleException
* If guacamole.properties cannot be parsed.
*/
public String getServerHostname() throws GuacamoleException {
return environment.getProperty(
LDAPGuacamoleProperties.LDAP_HOSTNAME,
"localhost"
);
}
/**
* Returns the port of the LDAP server configured with
* guacamole.properties. The default value depends on which encryption
* method is being used. For unencrypted LDAP and STARTTLS, this will be
* 389. For LDAPS (LDAP over SSL) this will be 636.
*
* @return
* The port of the LDAP server, as configured with
* guacamole.properties.
*
* @throws GuacamoleException
* If guacamole.properties cannot be parsed.
*/
public int getServerPort() throws GuacamoleException {
return environment.getProperty(
LDAPGuacamoleProperties.LDAP_PORT,
getEncryptionMethod().DEFAULT_PORT
);
}
/**
* Returns all username attributes which should be used to query and bind
* users using the LDAP directory. By default, this will be "uid" - a
* common attribute used for this purpose.
*
* @return
* The username attributes which should be used to query and bind users
* using the LDAP directory.
*
* @throws GuacamoleException
* If guacamole.properties cannot be parsed.
*/
public List<String> getUsernameAttributes() throws GuacamoleException {
return environment.getProperty(
LDAPGuacamoleProperties.LDAP_USERNAME_ATTRIBUTE,
Collections.singletonList("uid")
);
}
/**
* Returns the base DN under which all Guacamole users will be stored
* within the LDAP directory.
*
* @return
* The base DN under which all Guacamole users will be stored within
* the LDAP directory.
*
* @throws GuacamoleException
* If guacamole.properties cannot be parsed, or if the user base DN
* property is not specified.
*/
public Dn getUserBaseDN() throws GuacamoleException {
return environment.getRequiredProperty(
LDAPGuacamoleProperties.LDAP_USER_BASE_DN
);
}
/**
* Returns the base DN under which all Guacamole configurations
* (connections) will be stored within the LDAP directory. If Guacamole
* configurations will not be stored within LDAP, null is returned.
*
* @return
* The base DN under which all Guacamole configurations will be stored
* within the LDAP directory, or null if no Guacamole configurations
* will be stored within the LDAP directory.
*
* @throws GuacamoleException
* If guacamole.properties cannot be parsed.
*/
public Dn getConfigurationBaseDN() throws GuacamoleException {
return environment.getProperty(
LDAPGuacamoleProperties.LDAP_CONFIG_BASE_DN
);
}
/**
* Returns all attributes which should be used to determine the unique
* identifier of each user group. By default, this will be "cn".
*
* @return
* The attributes which should be used to determine the unique
* identifier of each group.
*
* @throws GuacamoleException
* If guacamole.properties cannot be parsed.
*/
public List<String> getGroupNameAttributes() throws GuacamoleException {
return environment.getProperty(
LDAPGuacamoleProperties.LDAP_GROUP_NAME_ATTRIBUTE,
Collections.singletonList("cn")
);
}
/**
* Returns the base DN under which all Guacamole role based access control
* (RBAC) groups will be stored within the LDAP directory. If RBAC will not
* be used, null is returned.
*
* @return
* The base DN under which all Guacamole RBAC groups will be stored
* within the LDAP directory, or null if RBAC will not be used.
*
* @throws GuacamoleException
* If guacamole.properties cannot be parsed.
*/
public Dn getGroupBaseDN() throws GuacamoleException {
return environment.getProperty(
LDAPGuacamoleProperties.LDAP_GROUP_BASE_DN
);
}
/**
* Returns the login that should be used when searching for the DNs of users
* attempting to authenticate. If no such search should be performed, null
* is returned. * is returned.
* *
* @return * @param username
* The DN that should be used when searching for the DNs of users * The username of the user whose corresponding LDAP server
* attempting to authenticate, or null if no such search should be * configuration should be retrieved.
* performed.
*
* @throws GuacamoleException
* If guacamole.properties cannot be parsed.
*/
public String getSearchBindDN() throws GuacamoleException {
return environment.getProperty(
LDAPGuacamoleProperties.LDAP_SEARCH_BIND_DN
);
}
/**
* Returns the password that should be used when binding to the LDAP server
* using the DN returned by getSearchBindDN(). If no password should be
* used, null is returned.
* *
* @return * @return
* The password that should be used when binding to the LDAP server * The configuration of the LDAP server related to the user having the
* using the DN returned by getSearchBindDN(), or null if no password * given username, or null if no such LDAP server is defined.
* should be used.
* *
* @throws GuacamoleException * @throws GuacamoleException
* If guacamole.properties cannot be parsed. * If the configuration information of the LDAP server related to the
* user having the given username cannot be retrieved due to an error.
*/ */
public String getSearchBindPassword() throws GuacamoleException { public LDAPConfiguration getLDAPConfiguration(String username) throws GuacamoleException {
return environment.getProperty( return new EnvironmentLDAPConfiguration(environment);
LDAPGuacamoleProperties.LDAP_SEARCH_BIND_PASSWORD
);
}
/**
* Returns the encryption method that should be used when connecting to the
* LDAP server. By default, no encryption is used.
*
* @return
* The encryption method that should be used when connecting to the
* LDAP server.
*
* @throws GuacamoleException
* If guacamole.properties cannot be parsed.
*/
public EncryptionMethod getEncryptionMethod() throws GuacamoleException {
return environment.getProperty(
LDAPGuacamoleProperties.LDAP_ENCRYPTION_METHOD,
EncryptionMethod.NONE
);
}
/**
* Returns maximum number of results a LDAP query can return,
* as configured with guacamole.properties.
* By default, this will be 1000.
*
* @return
* The maximum number of results a LDAP query can return,
* as configured with guacamole.properties.
*
* @throws GuacamoleException
* If guacamole.properties cannot be parsed.
*/
public int getMaxResults() throws GuacamoleException {
return environment.getProperty(
LDAPGuacamoleProperties.LDAP_MAX_SEARCH_RESULTS,
1000
);
}
/**
* Returns whether or not LDAP aliases will be dereferenced,
* as configured with guacamole.properties. The default
* behavior if not explicitly defined is to never
* dereference them.
*
* @return
* The behavior for handling dereferencing of aliases
* as configured in guacamole.properties.
*
* @throws GuacamoleException
* If guacamole.properties cannot be parsed.
*/
public AliasDerefMode getDereferenceAliases() throws GuacamoleException {
return environment.getProperty(
LDAPGuacamoleProperties.LDAP_DEREFERENCE_ALIASES,
AliasDerefMode.NEVER_DEREF_ALIASES
);
}
/**
* Returns the boolean value for whether the connection should
* follow referrals or not. By default, it will not.
*
* @return
* The boolean value of whether to follow referrals
* as configured in guacamole.properties.
*
* @throws GuacamoleException
* If guacamole.properties cannot be parsed.
*/
public boolean getFollowReferrals() throws GuacamoleException {
return environment.getProperty(
LDAPGuacamoleProperties.LDAP_FOLLOW_REFERRALS,
false
);
}
/**
* Returns the maximum number of referral hops to follow. By default
* a maximum of 5 hops is allowed.
*
* @return
* The maximum number of referral hops to follow
* as configured in guacamole.properties.
*
* @throws GuacamoleException
* If guacamole.properties cannot be parsed.
*/
public int getMaxReferralHops() throws GuacamoleException {
return environment.getProperty(
LDAPGuacamoleProperties.LDAP_MAX_REFERRAL_HOPS,
5
);
}
/**
* Returns the search filter that should be used when querying the
* LDAP server for Guacamole users. If no filter is specified,
* a default of "(objectClass=user)" is returned.
*
* @return
* The search filter that should be used when querying the
* LDAP server for users that are valid in Guacamole, or
* "(objectClass=user)" if not specified.
*
* @throws GuacamoleException
* If guacamole.properties cannot be parsed.
*/
public ExprNode getUserSearchFilter() throws GuacamoleException {
return environment.getProperty(
LDAPGuacamoleProperties.LDAP_USER_SEARCH_FILTER,
new PresenceNode("objectClass")
);
}
/**
* Returns the search filter that should be used when querying the
* LDAP server for Guacamole groups. If no filter is specified,
* a default of "(objectClass=*)" is used.
*
* @return
* The search filter that should be used when querying the
* LDAP server for groups that are valid in Guacamole, or
* "(objectClass=*)" if not specified.
*
* @throws GuacamoleException
* If guacamole.properties cannot be parsed.
*/
public ExprNode getGroupSearchFilter() throws GuacamoleException {
return environment.getProperty(
LDAPGuacamoleProperties.LDAP_GROUP_SEARCH_FILTER,
new PresenceNode("objectClass")
);
}
/**
* Returns the maximum number of seconds to wait for LDAP operations.
*
* @return
* The maximum number of seconds to wait for LDAP operations
* as configured in guacamole.properties.
*
* @throws GuacamoleException
* If guacamole.properties cannot be parsed.
*/
public int getOperationTimeout() throws GuacamoleException {
return environment.getProperty(
LDAPGuacamoleProperties.LDAP_OPERATION_TIMEOUT,
30
);
}
/**
* Returns names for custom LDAP user attributes. By default no
* attributes will be returned.
*
* @return
* Custom LDAP user attributes as configured in guacamole.properties.
*
* @throws GuacamoleException
* If guacamole.properties cannot be parsed.
*/
public List<String> getAttributes() throws GuacamoleException {
return environment.getProperty(
LDAPGuacamoleProperties.LDAP_USER_ATTRIBUTES,
Collections.<String>emptyList()
);
}
/**
* Returns the name of the LDAP attribute used to enumerate
* members in a group, or "member" by default.
*
* @return
* The name of the LDAP attribute to use to enumerate
* members in a group.
*
* @throws GuacamoleException
* If guacamole.properties connect be parsed.
*/
public String getMemberAttribute() throws GuacamoleException {
return environment.getProperty(
LDAPGuacamoleProperties.LDAP_MEMBER_ATTRIBUTE,
"member"
);
}
/**
* Returns whether the LDAP attribute used to enumerate members in a group
* specifies UID or DN.
*
* @return
* The type of data contained in the LDAP attribute used to enumerate
* members in a group, as configured in guacamole.properties
*
* @throws GuacamoleException
* If guacamole.properties cannot be parsed.
*/
public MemberAttributeType getMemberAttributeType()
throws GuacamoleException {
return environment.getProperty(
LDAPGuacamoleProperties.LDAP_MEMBER_ATTRIBUTE_TYPE,
MemberAttributeType.DN
);
} }
} }

View File

@@ -0,0 +1,209 @@
/*
* 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.guacamole.auth.ldap.conf;
import java.util.Collections;
import java.util.List;
import org.apache.directory.api.ldap.model.filter.ExprNode;
import org.apache.directory.api.ldap.model.filter.PresenceNode;
import org.apache.directory.api.ldap.model.message.AliasDerefMode;
import org.apache.directory.api.ldap.model.name.Dn;
import org.apache.guacamole.GuacamoleException;
import org.apache.guacamole.environment.Environment;
/**
* LDAPConfiguration implementation that reads its configuration details from
* guacamole.properties.
*/
public class EnvironmentLDAPConfiguration implements LDAPConfiguration {
/**
* The Guacamole server environment.
*/
private final Environment environment;
/**
* Creates a new EnvironmentLDAPConfiguration that reads its configuration
* details from guacamole.properties, as exposed by the given Environment.
*
* @param environment
* The Guacamole server environment.
*/
public EnvironmentLDAPConfiguration(Environment environment) {
this.environment = environment;
}
@Override
public String getServerHostname() throws GuacamoleException {
return environment.getProperty(
LDAPGuacamoleProperties.LDAP_HOSTNAME,
"localhost"
);
}
@Override
public int getServerPort() throws GuacamoleException {
return environment.getProperty(
LDAPGuacamoleProperties.LDAP_PORT,
getEncryptionMethod().DEFAULT_PORT
);
}
@Override
public List<String> getUsernameAttributes() throws GuacamoleException {
return environment.getProperty(
LDAPGuacamoleProperties.LDAP_USERNAME_ATTRIBUTE,
Collections.singletonList("uid")
);
}
@Override
public Dn getUserBaseDN() throws GuacamoleException {
return environment.getRequiredProperty(
LDAPGuacamoleProperties.LDAP_USER_BASE_DN
);
}
@Override
public Dn getConfigurationBaseDN() throws GuacamoleException {
return environment.getProperty(
LDAPGuacamoleProperties.LDAP_CONFIG_BASE_DN
);
}
@Override
public List<String> getGroupNameAttributes() throws GuacamoleException {
return environment.getProperty(
LDAPGuacamoleProperties.LDAP_GROUP_NAME_ATTRIBUTE,
Collections.singletonList("cn")
);
}
@Override
public Dn getGroupBaseDN() throws GuacamoleException {
return environment.getProperty(
LDAPGuacamoleProperties.LDAP_GROUP_BASE_DN
);
}
@Override
public String getSearchBindDN() throws GuacamoleException {
return environment.getProperty(
LDAPGuacamoleProperties.LDAP_SEARCH_BIND_DN
);
}
@Override
public String getSearchBindPassword() throws GuacamoleException {
return environment.getProperty(
LDAPGuacamoleProperties.LDAP_SEARCH_BIND_PASSWORD
);
}
@Override
public EncryptionMethod getEncryptionMethod() throws GuacamoleException {
return environment.getProperty(
LDAPGuacamoleProperties.LDAP_ENCRYPTION_METHOD,
EncryptionMethod.NONE
);
}
@Override
public int getMaxResults() throws GuacamoleException {
return environment.getProperty(
LDAPGuacamoleProperties.LDAP_MAX_SEARCH_RESULTS,
1000
);
}
@Override
public AliasDerefMode getDereferenceAliases() throws GuacamoleException {
return environment.getProperty(
LDAPGuacamoleProperties.LDAP_DEREFERENCE_ALIASES,
AliasDerefMode.NEVER_DEREF_ALIASES
);
}
@Override
public boolean getFollowReferrals() throws GuacamoleException {
return environment.getProperty(
LDAPGuacamoleProperties.LDAP_FOLLOW_REFERRALS,
false
);
}
@Override
public int getMaxReferralHops() throws GuacamoleException {
return environment.getProperty(
LDAPGuacamoleProperties.LDAP_MAX_REFERRAL_HOPS,
5
);
}
@Override
public ExprNode getUserSearchFilter() throws GuacamoleException {
return environment.getProperty(
LDAPGuacamoleProperties.LDAP_USER_SEARCH_FILTER,
new PresenceNode("objectClass")
);
}
@Override
public ExprNode getGroupSearchFilter() throws GuacamoleException {
return environment.getProperty(
LDAPGuacamoleProperties.LDAP_GROUP_SEARCH_FILTER,
new PresenceNode("objectClass")
);
}
@Override
public int getOperationTimeout() throws GuacamoleException {
return environment.getProperty(
LDAPGuacamoleProperties.LDAP_OPERATION_TIMEOUT,
30
);
}
@Override
public List<String> getAttributes() throws GuacamoleException {
return environment.getProperty(
LDAPGuacamoleProperties.LDAP_USER_ATTRIBUTES,
Collections.<String>emptyList()
);
}
@Override
public String getMemberAttribute() throws GuacamoleException {
return environment.getProperty(
LDAPGuacamoleProperties.LDAP_MEMBER_ATTRIBUTE,
"member"
);
}
@Override
public MemberAttributeType getMemberAttributeType()
throws GuacamoleException {
return environment.getProperty(
LDAPGuacamoleProperties.LDAP_MEMBER_ATTRIBUTE_TYPE,
MemberAttributeType.DN
);
}
}

View File

@@ -0,0 +1,303 @@
/*
* 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.guacamole.auth.ldap.conf;
import java.util.List;
import org.apache.directory.api.ldap.model.filter.ExprNode;
import org.apache.directory.api.ldap.model.message.AliasDerefMode;
import org.apache.directory.api.ldap.model.name.Dn;
import org.apache.guacamole.GuacamoleException;
/**
* Configuration information defining how a particular LDAP server should be
* queried.
*/
public interface LDAPConfiguration {
/**
* Returns the hostname or IP address of the LDAP server. By default, this
* will be "localhost".
*
* @return
* The hostname or IP address of the LDAP server.
*
* @throws GuacamoleException
* If the hostname or IP address of the LDAP server cannot be
* retrieved.
*/
String getServerHostname() throws GuacamoleException;
/**
* Returns the port of the LDAP server. The default value depends on which
* encryption method is being used. For unencrypted LDAP and STARTTLS, this
* will be 389. For LDAPS (LDAP over SSL) this will be 636.
*
* @return
* The port of the LDAP server.
*
* @throws GuacamoleException
* If the port of the LDAP server cannot be retrieved.
*/
int getServerPort() throws GuacamoleException;
/**
* Returns all username attributes which should be used to query and bind
* users using the LDAP directory. By default, this will be "uid" - a
* common attribute used for this purpose.
*
* @return
* The username attributes which should be used to query and bind users
* using the LDAP directory.
*
* @throws GuacamoleException
* If the username attributes cannot be retrieved.
*/
List<String> getUsernameAttributes() throws GuacamoleException;
/**
* Returns the base DN under which all Guacamole users will be stored
* within the LDAP directory.
*
* @return
* The base DN under which all Guacamole users will be stored within
* the LDAP directory.
*
* @throws GuacamoleException
* If the user base DN cannot be retrieved.
*/
Dn getUserBaseDN() throws GuacamoleException;
/**
* Returns the base DN under which all Guacamole configurations
* (connections) will be stored within the LDAP directory. If Guacamole
* configurations will not be stored within LDAP, null is returned.
*
* @return
* The base DN under which all Guacamole configurations will be stored
* within the LDAP directory, or null if no Guacamole configurations
* will be stored within the LDAP directory.
*
* @throws GuacamoleException
* If the configuration base DN cannot be retrieved.
*/
Dn getConfigurationBaseDN() throws GuacamoleException;
/**
* Returns all attributes which should be used to determine the unique
* identifier of each user group. By default, this will be "cn".
*
* @return
* The attributes which should be used to determine the unique
* identifier of each group.
*
* @throws GuacamoleException
* If the group name attributes cannot be retrieved.
*/
List<String> getGroupNameAttributes() throws GuacamoleException;
/**
* Returns the base DN under which all Guacamole role based access control
* (RBAC) groups will be stored within the LDAP directory. If RBAC will not
* be used, null is returned.
*
* @return
* The base DN under which all Guacamole RBAC groups will be stored
* within the LDAP directory, or null if RBAC will not be used.
*
* @throws GuacamoleException
* If the group base DN cannot be retrieved.
*/
Dn getGroupBaseDN() throws GuacamoleException;
/**
* Returns the login that should be used when searching for the DNs of users
* attempting to authenticate. If no such search should be performed, null
* is returned.
*
* @return
* The DN that should be used when searching for the DNs of users
* attempting to authenticate, or null if no such search should be
* performed.
*
* @throws GuacamoleException
* If the search bind DN cannot be retrieved.
*/
String getSearchBindDN() throws GuacamoleException;
/**
* Returns the password that should be used when binding to the LDAP server
* using the DN returned by getSearchBindDN(). If no password should be
* used, null is returned.
*
* @return
* The password that should be used when binding to the LDAP server
* using the DN returned by getSearchBindDN(), or null if no password
* should be used.
*
* @throws GuacamoleException
* If the search bind password cannot be retrieved.
*/
String getSearchBindPassword() throws GuacamoleException;
/**
* Returns the encryption method that should be used when connecting to the
* LDAP server. By default, no encryption is used.
*
* @return
* The encryption method that should be used when connecting to the
* LDAP server.
*
* @throws GuacamoleException
* If the encryption method cannot be retrieved.
*/
EncryptionMethod getEncryptionMethod() throws GuacamoleException;
/**
* Returns maximum number of results a LDAP query can return. By default,
* this will be 1000.
*
* @return
* The maximum number of results a LDAP query can return.
*
* @throws GuacamoleException
* If the maximum number of results cannot be retrieved.
*/
int getMaxResults() throws GuacamoleException;
/**
* Returns whether or not LDAP aliases will be dereferenced. By default,
* aliases are never dereferenced.
*
* @return
* The LDAP alias dereferencing mode.
*
* @throws GuacamoleException
* If the LDAP alias dereferencing mode cannot be retrieved.
*/
AliasDerefMode getDereferenceAliases() throws GuacamoleException;
/**
* Returns whether referrals should be automatically followed. By default,
* referrals are not followed.
*
* @return
* Whether referrals should be followed.
*
* @throws GuacamoleException
* If the configuration information determining whether LDAP referrals
* should be followed cannot be retrieved.
*/
boolean getFollowReferrals() throws GuacamoleException;
/**
* Returns the maximum number of referral hops to follow. By default
* a maximum of 5 hops is allowed.
*
* @return
* The maximum number of referral hops to follow.
*
* @throws GuacamoleException
* If the maximum number of referral hops cannot be retrieved.
*/
int getMaxReferralHops() throws GuacamoleException;
/**
* Returns the search filter that should be used when querying the
* LDAP server for Guacamole users. If no filter is specified,
* a default of "(objectClass=user)" is returned.
*
* @return
* The search filter that should be used when querying the
* LDAP server for users that are valid in Guacamole, or
* "(objectClass=user)" if not specified.
*
* @throws GuacamoleException
* If the user search filter cannot be retrieved.
*/
ExprNode getUserSearchFilter() throws GuacamoleException;
/**
* Returns the search filter that should be used when querying the
* LDAP server for Guacamole groups. If no filter is specified,
* a default of "(objectClass=*)" is used.
*
* @return
* The search filter that should be used when querying the
* LDAP server for groups that are valid in Guacamole, or
* "(objectClass=*)" if not specified.
*
* @throws GuacamoleException
* If the group search filter cannot be retrieved.
*/
ExprNode getGroupSearchFilter() throws GuacamoleException;
/**
* Returns the maximum number of seconds to wait for LDAP operations.
*
* @return
* The maximum number of seconds to wait for LDAP operations.
*
* @throws GuacamoleException
* If the LDAP operation timeout cannot be retrieved.
*/
int getOperationTimeout() throws GuacamoleException;
/**
* Returns names for custom LDAP user attributes that should be made
* available as parameter tokens. By default, no additional LDAP attributes
* will be exposed as parameter tokens.
*
* @return
* A list of all LDAP user attributes that should be made available as
* parameter tokens.
*
* @throws GuacamoleException
* If the names of custom LDAP user attributes cannot be retrieved.
*/
List<String> getAttributes() throws GuacamoleException;
/**
* Returns the name of the LDAP attribute used to enumerate members in a
* group. By default, this will be "member".
*
* @return
* The name of the LDAP attribute to use to enumerate
* members in a group.
*
* @throws GuacamoleException
* If the group member attribute cannot be retrieved.
*/
String getMemberAttribute() throws GuacamoleException;
/**
* Returns whether the LDAP attribute used to enumerate members in a group
* specifies a UID or DN.
*
* @return
* The type of data contained in the LDAP attribute used to enumerate
* members in a group.
*
* @throws GuacamoleException
* If the type of attribute used to enumerate group members cannot be
* retrieved.
*/
MemberAttributeType getMemberAttributeType() throws GuacamoleException;
}

View File

@@ -38,13 +38,12 @@ import org.apache.directory.api.ldap.model.name.Dn;
import org.apache.directory.ldap.client.api.LdapConnectionConfig; import org.apache.directory.ldap.client.api.LdapConnectionConfig;
import org.apache.directory.ldap.client.api.LdapNetworkConnection; import org.apache.directory.ldap.client.api.LdapNetworkConnection;
import org.apache.guacamole.auth.ldap.LDAPAuthenticationProvider; import org.apache.guacamole.auth.ldap.LDAPAuthenticationProvider;
import org.apache.guacamole.auth.ldap.conf.ConfigurationService;
import org.apache.guacamole.GuacamoleException; import org.apache.guacamole.GuacamoleException;
import org.apache.guacamole.GuacamoleServerException; import org.apache.guacamole.GuacamoleServerException;
import org.apache.guacamole.auth.ldap.ObjectQueryService; import org.apache.guacamole.auth.ldap.ObjectQueryService;
import org.apache.guacamole.auth.ldap.conf.LDAPConfiguration;
import org.apache.guacamole.auth.ldap.group.UserGroupService; import org.apache.guacamole.auth.ldap.group.UserGroupService;
import org.apache.guacamole.auth.ldap.user.LDAPAuthenticatedUser; import org.apache.guacamole.auth.ldap.user.LDAPAuthenticatedUser;
import org.apache.guacamole.net.auth.AuthenticatedUser;
import org.apache.guacamole.net.auth.Connection; import org.apache.guacamole.net.auth.Connection;
import org.apache.guacamole.net.auth.TokenInjectingConnection; import org.apache.guacamole.net.auth.TokenInjectingConnection;
import org.apache.guacamole.net.auth.simple.SimpleConnection; import org.apache.guacamole.net.auth.simple.SimpleConnection;
@@ -63,12 +62,6 @@ public class ConnectionService {
*/ */
private static final Logger logger = LoggerFactory.getLogger(ConnectionService.class); private static final Logger logger = LoggerFactory.getLogger(ConnectionService.class);
/**
* Service for retrieving LDAP server configuration information.
*/
@Inject
private ConfigurationService confService;
/** /**
* Service for executing LDAP queries. * Service for executing LDAP queries.
*/ */
@@ -143,11 +136,13 @@ public class ConnectionService {
* @throws GuacamoleException * @throws GuacamoleException
* If an error occurs preventing retrieval of connections. * If an error occurs preventing retrieval of connections.
*/ */
public Map<String, Connection> getConnections(AuthenticatedUser user, public Map<String, Connection> getConnections(LDAPAuthenticatedUser user,
LdapNetworkConnection ldapConnection) throws GuacamoleException { LdapNetworkConnection ldapConnection) throws GuacamoleException {
LDAPConfiguration ldapConfig = user.getLDAPConfiguration();
// Do not return any connections if base DN is not specified // Do not return any connections if base DN is not specified
Dn configurationBaseDN = confService.getConfigurationBaseDN(); Dn configurationBaseDN = ldapConfig.getConfigurationBaseDN();
if (configurationBaseDN == null) if (configurationBaseDN == null)
return Collections.<String, Connection>emptyMap(); return Collections.<String, Connection>emptyMap();
@@ -164,13 +159,13 @@ public class ConnectionService {
// Get the search filter for finding connections accessible by the // Get the search filter for finding connections accessible by the
// current user // current user
ExprNode connectionSearchFilter = getConnectionSearchFilter(userDN, ldapConnection); ExprNode connectionSearchFilter = getConnectionSearchFilter(user, userDN, ldapConnection);
// Find all Guacamole connections for the given user by // Find all Guacamole connections for the given user by
// looking for direct membership in the guacConfigGroup // looking for direct membership in the guacConfigGroup
// and possibly any groups the user is a member of that are // and possibly any groups the user is a member of that are
// referred to in the seeAlso attribute of the guacConfigGroup. // referred to in the seeAlso attribute of the guacConfigGroup.
List<Entry> results = queryService.search(ldapConnection, List<Entry> results = queryService.search(ldapConfig, ldapConnection,
configurationBaseDN, connectionSearchFilter, 0, GUAC_CONFIG_LDAP_ATTRIBUTES); configurationBaseDN, connectionSearchFilter, 0, GUAC_CONFIG_LDAP_ATTRIBUTES);
// Return a map of all readable connections // Return a map of all readable connections
@@ -261,8 +256,7 @@ public class ConnectionService {
// Inject LDAP-specific tokens only if LDAP handled user // Inject LDAP-specific tokens only if LDAP handled user
// authentication // authentication
if (user instanceof LDAPAuthenticatedUser) if (user instanceof LDAPAuthenticatedUser)
connection = new TokenInjectingConnection(connection, connection = new TokenInjectingConnection(connection, user.getTokens());
((LDAPAuthenticatedUser) user).getTokens());
return connection; return connection;
@@ -279,6 +273,10 @@ public class ConnectionService {
* Returns an LDAP search filter which queries all connections accessible * Returns an LDAP search filter which queries all connections accessible
* by the user having the given DN. * by the user having the given DN.
* *
* @param user
* The AuthenticatedUser object associated with the user who is
* currently authenticated with Guacamole.
*
* @param userDN * @param userDN
* DN of the user to search for associated guacConfigGroup connections. * DN of the user to search for associated guacConfigGroup connections.
* *
@@ -296,10 +294,12 @@ public class ConnectionService {
* @throws GuacamoleException * @throws GuacamoleException
* If an error occurs retrieving the group base DN. * If an error occurs retrieving the group base DN.
*/ */
private ExprNode getConnectionSearchFilter(Dn userDN, private ExprNode getConnectionSearchFilter(LDAPAuthenticatedUser user,
LdapNetworkConnection ldapConnection) Dn userDN, LdapNetworkConnection ldapConnection)
throws LdapException, GuacamoleException { throws LdapException, GuacamoleException {
LDAPConfiguration config = user.getLDAPConfiguration();
AndNode searchFilter = new AndNode(); AndNode searchFilter = new AndNode();
// Add the prefix to the search filter, prefix filter searches for guacConfigGroups with the userDN as the member attribute value // Add the prefix to the search filter, prefix filter searches for guacConfigGroups with the userDN as the member attribute value
@@ -307,12 +307,12 @@ public class ConnectionService {
// Apply group filters // Apply group filters
OrNode groupFilter = new OrNode(); OrNode groupFilter = new OrNode();
groupFilter.addNode(new EqualityNode(confService.getMemberAttribute(), groupFilter.addNode(new EqualityNode(config.getMemberAttribute(),
userDN.toString())); userDN.toString()));
// Additionally filter by group membership if the current user is a // Additionally filter by group membership if the current user is a
// member of any user groups // member of any user groups
List<Entry> userGroups = userGroupService.getParentUserGroupEntries(ldapConnection, userDN); List<Entry> userGroups = userGroupService.getParentUserGroupEntries(config, ldapConnection, userDN);
if (!userGroups.isEmpty()) { if (!userGroups.isEmpty()) {
userGroups.forEach(entry -> userGroups.forEach(entry ->
groupFilter.addNode(new EqualityNode(LDAP_ATTRIBUTE_NAME_GROUPS,entry.getDn().toString())) groupFilter.addNode(new EqualityNode(LDAP_ATTRIBUTE_NAME_GROUPS,entry.getDn().toString()))

View File

@@ -34,10 +34,11 @@ import org.apache.directory.api.ldap.model.filter.ExprNode;
import org.apache.directory.api.ldap.model.filter.NotNode; import org.apache.directory.api.ldap.model.filter.NotNode;
import org.apache.directory.api.ldap.model.name.Dn; import org.apache.directory.api.ldap.model.name.Dn;
import org.apache.directory.ldap.client.api.LdapNetworkConnection; import org.apache.directory.ldap.client.api.LdapNetworkConnection;
import org.apache.guacamole.auth.ldap.conf.ConfigurationService;
import org.apache.guacamole.auth.ldap.conf.MemberAttributeType; import org.apache.guacamole.auth.ldap.conf.MemberAttributeType;
import org.apache.guacamole.GuacamoleException; import org.apache.guacamole.GuacamoleException;
import org.apache.guacamole.auth.ldap.ObjectQueryService; import org.apache.guacamole.auth.ldap.ObjectQueryService;
import org.apache.guacamole.auth.ldap.conf.LDAPConfiguration;
import org.apache.guacamole.auth.ldap.user.LDAPAuthenticatedUser;
import org.apache.guacamole.net.auth.UserGroup; import org.apache.guacamole.net.auth.UserGroup;
import org.apache.guacamole.net.auth.simple.SimpleUserGroup; import org.apache.guacamole.net.auth.simple.SimpleUserGroup;
import org.slf4j.Logger; import org.slf4j.Logger;
@@ -54,12 +55,6 @@ public class UserGroupService {
*/ */
private static final Logger logger = LoggerFactory.getLogger(UserGroupService.class); private static final Logger logger = LoggerFactory.getLogger(UserGroupService.class);
/**
* Service for retrieving LDAP server configuration information.
*/
@Inject
private ConfigurationService confService;
/** /**
* Service for executing LDAP queries. * Service for executing LDAP queries.
*/ */
@@ -73,22 +68,25 @@ public class UserGroupService {
* defined (may always return zero results), it should only be explicitly * defined (may always return zero results), it should only be explicitly
* excluded if it is expected to have been defined. * excluded if it is expected to have been defined.
* *
* @param config
* The configuration of the LDAP server being queried.
*
* @return * @return
* The base search filter which should be used to retrieve user groups. * The base search filter which should be used to retrieve user groups.
* *
* @throws GuacamoleException * @throws GuacamoleException
* If guacamole.properties cannot be parsed. * If guacamole.properties cannot be parsed.
*/ */
private ExprNode getGroupSearchFilter() throws GuacamoleException { private ExprNode getGroupSearchFilter(LDAPConfiguration config) throws GuacamoleException {
// Use filter defined by "ldap-group-search-filter" as basis for all // Use filter defined by "ldap-group-search-filter" as basis for all
// retrieval of user groups // retrieval of user groups
ExprNode groupFilter = confService.getGroupSearchFilter(); ExprNode groupFilter = config.getGroupSearchFilter();
// Explicitly exclude guacConfigGroup object class only if it should // Explicitly exclude guacConfigGroup object class only if it should
// be assumed to be defined (query may fail due to no such object // be assumed to be defined (query may fail due to no such object
// class existing otherwise) // class existing otherwise)
if (confService.getConfigurationBaseDN() != null) { if (config.getConfigurationBaseDN() != null) {
groupFilter = new AndNode( groupFilter = new AndNode(
groupFilter, groupFilter,
new NotNode(new EqualityNode<String>("objectClass", "guacConfigGroup")) new NotNode(new EqualityNode<String>("objectClass", "guacConfigGroup"))
@@ -103,6 +101,10 @@ public class UserGroupService {
* Returns all Guacamole user groups accessible to the user currently bound * Returns all Guacamole user groups accessible to the user currently bound
* under the given LDAP connection. * under the given LDAP connection.
* *
* @param user
* The AuthenticatedUser object associated with the user who is
* currently authenticated with Guacamole.
*
* @param ldapConnection * @param ldapConnection
* The current connection to the LDAP server, associated with the * The current connection to the LDAP server, associated with the
* current user. * current user.
@@ -115,25 +117,28 @@ public class UserGroupService {
* @throws GuacamoleException * @throws GuacamoleException
* If an error occurs preventing retrieval of user groups. * If an error occurs preventing retrieval of user groups.
*/ */
public Map<String, UserGroup> getUserGroups(LdapNetworkConnection ldapConnection) public Map<String, UserGroup> getUserGroups(LDAPAuthenticatedUser user,
throws GuacamoleException { LdapNetworkConnection ldapConnection) throws GuacamoleException {
LDAPConfiguration config = user.getLDAPConfiguration();
// Do not return any user groups if base DN is not specified // Do not return any user groups if base DN is not specified
Dn groupBaseDN = confService.getGroupBaseDN(); Dn groupBaseDN = config.getGroupBaseDN();
if (groupBaseDN == null) if (groupBaseDN == null)
return Collections.emptyMap(); return Collections.emptyMap();
// Gather all attributes relevant for a group // Gather all attributes relevant for a group
String memberAttribute = confService.getMemberAttribute(); String memberAttribute = config.getMemberAttribute();
Collection<String> groupAttributes = new HashSet<>(confService.getGroupNameAttributes()); Collection<String> groupAttributes = new HashSet<>(config.getGroupNameAttributes());
groupAttributes.add(memberAttribute); groupAttributes.add(memberAttribute);
// Retrieve all visible user groups which are not guacConfigGroups // Retrieve all visible user groups which are not guacConfigGroups
Collection<String> attributes = confService.getGroupNameAttributes(); Collection<String> attributes = config.getGroupNameAttributes();
List<Entry> results = queryService.search( List<Entry> results = queryService.search(
config,
ldapConnection, ldapConnection,
groupBaseDN, groupBaseDN,
getGroupSearchFilter(), getGroupSearchFilter(config),
attributes, attributes,
null, null,
groupAttributes groupAttributes
@@ -167,6 +172,9 @@ public class UserGroupService {
* user is a member of. Only user groups which are readable by the current * user is a member of. Only user groups which are readable by the current
* user will be retrieved. * user will be retrieved.
* *
* @param config
* The configuration of the LDAP server being queried.
*
* @param ldapConnection * @param ldapConnection
* The current connection to the LDAP server, associated with the * The current connection to the LDAP server, associated with the
* current user. * current user.
@@ -181,24 +189,26 @@ public class UserGroupService {
* @throws GuacamoleException * @throws GuacamoleException
* If an error occurs preventing retrieval of user groups. * If an error occurs preventing retrieval of user groups.
*/ */
public List<Entry> getParentUserGroupEntries(LdapNetworkConnection ldapConnection, public List<Entry> getParentUserGroupEntries(LDAPConfiguration config,
Dn userDN) throws GuacamoleException { LdapNetworkConnection ldapConnection, Dn userDN)
throws GuacamoleException {
// Do not return any user groups if base DN is not specified // Do not return any user groups if base DN is not specified
Dn groupBaseDN = confService.getGroupBaseDN(); Dn groupBaseDN = config.getGroupBaseDN();
if (groupBaseDN == null) if (groupBaseDN == null)
return Collections.emptyList(); return Collections.emptyList();
// memberAttribute specified in properties could contain DN or username // memberAttribute specified in properties could contain DN or username
MemberAttributeType memberAttributeType = confService.getMemberAttributeType(); MemberAttributeType memberAttributeType = config.getMemberAttributeType();
String userIDorDN = userDN.toString(); String userIDorDN = userDN.toString();
Collection<String> userAttributes = confService.getUsernameAttributes(); Collection<String> userAttributes = config.getUsernameAttributes();
if (memberAttributeType == MemberAttributeType.UID) { if (memberAttributeType == MemberAttributeType.UID) {
// Retrieve user objects with userDN // Retrieve user objects with userDN
List<Entry> userEntries = queryService.search( List<Entry> userEntries = queryService.search(
config,
ldapConnection, ldapConnection,
userDN, userDN,
confService.getUserSearchFilter(), config.getUserSearchFilter(),
0, 0,
userAttributes); userAttributes);
// ... there can surely only be one // ... there can surely only be one
@@ -222,16 +232,17 @@ public class UserGroupService {
} }
// Gather all attributes relevant for a group // Gather all attributes relevant for a group
String memberAttribute = confService.getMemberAttribute(); String memberAttribute = config.getMemberAttribute();
Collection<String> groupAttributes = new HashSet<>(confService.getGroupNameAttributes()); Collection<String> groupAttributes = new HashSet<>(config.getGroupNameAttributes());
groupAttributes.add(memberAttribute); groupAttributes.add(memberAttribute);
// Get all groups the user is a member of starting at the groupBaseDN, // Get all groups the user is a member of starting at the groupBaseDN,
// excluding guacConfigGroups // excluding guacConfigGroups
return queryService.search( return queryService.search(
config,
ldapConnection, ldapConnection,
groupBaseDN, groupBaseDN,
getGroupSearchFilter(), getGroupSearchFilter(config),
Collections.singleton(memberAttribute), Collections.singleton(memberAttribute),
userIDorDN, userIDorDN,
groupAttributes groupAttributes
@@ -244,6 +255,9 @@ public class UserGroupService {
* member of. Only identifiers of user groups which are readable by the * member of. Only identifiers of user groups which are readable by the
* current user will be retrieved. * current user will be retrieved.
* *
* @param config
* The configuration of the LDAP server being queried.
*
* @param ldapConnection * @param ldapConnection
* The current connection to the LDAP server, associated with the * The current connection to the LDAP server, associated with the
* current user. * current user.
@@ -258,11 +272,12 @@ public class UserGroupService {
* @throws GuacamoleException * @throws GuacamoleException
* If an error occurs preventing retrieval of user groups. * If an error occurs preventing retrieval of user groups.
*/ */
public Set<String> getParentUserGroupIdentifiers(LdapNetworkConnection ldapConnection, public Set<String> getParentUserGroupIdentifiers(LDAPConfiguration config,
Dn userDN) throws GuacamoleException { LdapNetworkConnection ldapConnection, Dn userDN)
throws GuacamoleException {
Collection<String> attributes = confService.getGroupNameAttributes(); Collection<String> attributes = config.getGroupNameAttributes();
List<Entry> userGroups = getParentUserGroupEntries(ldapConnection, userDN); List<Entry> userGroups = getParentUserGroupEntries(config, ldapConnection, userDN);
Set<String> identifiers = new HashSet<>(userGroups.size()); Set<String> identifiers = new HashSet<>(userGroups.size());
userGroups.forEach(entry -> { userGroups.forEach(entry -> {

View File

@@ -24,6 +24,7 @@ import java.util.Collections;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import org.apache.directory.api.ldap.model.name.Dn; import org.apache.directory.api.ldap.model.name.Dn;
import org.apache.guacamole.auth.ldap.conf.LDAPConfiguration;
import org.apache.guacamole.net.auth.AbstractAuthenticatedUser; import org.apache.guacamole.net.auth.AbstractAuthenticatedUser;
import org.apache.guacamole.net.auth.AuthenticationProvider; import org.apache.guacamole.net.auth.AuthenticationProvider;
import org.apache.guacamole.net.auth.Credentials; import org.apache.guacamole.net.auth.Credentials;
@@ -63,10 +64,20 @@ public class LDAPAuthenticatedUser extends AbstractAuthenticatedUser {
*/ */
private Dn bindDn; private Dn bindDn;
/**
* The configuration of the LDAP server that should be used for all queries
* related to this AuthenticatedUser.
*/
private LDAPConfiguration config;
/** /**
* Initializes this AuthenticatedUser with the given credentials, * Initializes this AuthenticatedUser with the given credentials,
* connection parameter tokens. and set of effective user groups. * connection parameter tokens. and set of effective user groups.
* *
* @param config
* The configuration of the LDAP server that should be used for all
* queries related to this AuthenticatedUser.
*
* @param credentials * @param credentials
* The credentials provided when this user was authenticated. * The credentials provided when this user was authenticated.
* *
@@ -81,8 +92,9 @@ public class LDAPAuthenticatedUser extends AbstractAuthenticatedUser {
* @param bindDn * @param bindDn
* The LDAP DN used to bind this user. * The LDAP DN used to bind this user.
*/ */
public void init(Credentials credentials, Map<String, String> tokens, public void init(LDAPConfiguration config, Credentials credentials,
Set<String> effectiveGroups, Dn bindDn) { Map<String, String> tokens, Set<String> effectiveGroups, Dn bindDn) {
this.config = config;
this.credentials = credentials; this.credentials = credentials;
this.tokens = Collections.unmodifiableMap(tokens); this.tokens = Collections.unmodifiableMap(tokens);
this.effectiveGroups = effectiveGroups; this.effectiveGroups = effectiveGroups;
@@ -114,6 +126,18 @@ public class LDAPAuthenticatedUser extends AbstractAuthenticatedUser {
return bindDn; return bindDn;
} }
/**
* Returns the configuration of the LDAP server that should be used for all
* queries related to this AuthenticatedUser.
*
* @return
* The configuration of the LDAP server related to this
* AuthenticatedUser.
*/
public LDAPConfiguration getLDAPConfiguration() {
return config;
}
@Override @Override
public AuthenticationProvider getAuthenticationProvider() { public AuthenticationProvider getAuthenticationProvider() {
return authProvider; return authProvider;

View File

@@ -27,7 +27,6 @@ import org.apache.guacamole.GuacamoleException;
import org.apache.guacamole.auth.ldap.LDAPAuthenticationProvider; import org.apache.guacamole.auth.ldap.LDAPAuthenticationProvider;
import org.apache.guacamole.auth.ldap.group.UserGroupService; import org.apache.guacamole.auth.ldap.group.UserGroupService;
import org.apache.guacamole.net.auth.AbstractUserContext; import org.apache.guacamole.net.auth.AbstractUserContext;
import org.apache.guacamole.net.auth.AuthenticatedUser;
import org.apache.guacamole.net.auth.AuthenticationProvider; import org.apache.guacamole.net.auth.AuthenticationProvider;
import org.apache.guacamole.net.auth.Connection; import org.apache.guacamole.net.auth.Connection;
import org.apache.guacamole.net.auth.ConnectionGroup; import org.apache.guacamole.net.auth.ConnectionGroup;
@@ -106,8 +105,8 @@ public class LDAPUserContext extends AbstractUserContext {
* *
* @param user * @param user
* The AuthenticatedUser representing the user that authenticated. This * The AuthenticatedUser representing the user that authenticated. This
* user may have been authenticated by a different authentication * user will always have been authenticated via LDAP, as LDAP data is
* provider (not LDAP). * not provided to non-LDAP users.
* *
* @param ldapConnection * @param ldapConnection
* The connection to the LDAP server to use when querying accessible * The connection to the LDAP server to use when querying accessible
@@ -117,17 +116,17 @@ public class LDAPUserContext extends AbstractUserContext {
* If associated data stored within the LDAP directory cannot be * If associated data stored within the LDAP directory cannot be
* queried due to an error. * queried due to an error.
*/ */
public void init(AuthenticatedUser user, LdapNetworkConnection ldapConnection) public void init(LDAPAuthenticatedUser user, LdapNetworkConnection ldapConnection)
throws GuacamoleException { throws GuacamoleException {
// Query all accessible users // Query all accessible users
userDirectory = new SimpleDirectory<>( userDirectory = new SimpleDirectory<>(
userService.getUsers(ldapConnection) userService.getUsers(user, ldapConnection)
); );
// Query all accessible user groups // Query all accessible user groups
userGroupDirectory = new SimpleDirectory<>( userGroupDirectory = new SimpleDirectory<>(
userGroupService.getUserGroups(ldapConnection) userGroupService.getUserGroups(user, ldapConnection)
); );
// Query all accessible connections // Query all accessible connections

View File

@@ -32,11 +32,11 @@ import org.apache.directory.api.ldap.model.exception.LdapInvalidAttributeValueEx
import org.apache.directory.api.ldap.model.name.Dn; import org.apache.directory.api.ldap.model.name.Dn;
import org.apache.directory.api.ldap.model.name.Rdn; import org.apache.directory.api.ldap.model.name.Rdn;
import org.apache.directory.ldap.client.api.LdapNetworkConnection; import org.apache.directory.ldap.client.api.LdapNetworkConnection;
import org.apache.guacamole.auth.ldap.conf.ConfigurationService;
import org.apache.guacamole.GuacamoleException; import org.apache.guacamole.GuacamoleException;
import org.apache.guacamole.GuacamoleServerException; import org.apache.guacamole.GuacamoleServerException;
import org.apache.guacamole.auth.ldap.conf.LDAPGuacamoleProperties; import org.apache.guacamole.auth.ldap.conf.LDAPGuacamoleProperties;
import org.apache.guacamole.auth.ldap.ObjectQueryService; import org.apache.guacamole.auth.ldap.ObjectQueryService;
import org.apache.guacamole.auth.ldap.conf.LDAPConfiguration;
import org.apache.guacamole.net.auth.User; import org.apache.guacamole.net.auth.User;
import org.apache.guacamole.net.auth.simple.SimpleUser; import org.apache.guacamole.net.auth.simple.SimpleUser;
import org.slf4j.Logger; import org.slf4j.Logger;
@@ -53,12 +53,6 @@ public class UserService {
*/ */
private static final Logger logger = LoggerFactory.getLogger(UserService.class); private static final Logger logger = LoggerFactory.getLogger(UserService.class);
/**
* Service for retrieving LDAP server configuration information.
*/
@Inject
private ConfigurationService confService;
/** /**
* Service for executing LDAP queries. * Service for executing LDAP queries.
*/ */
@@ -69,6 +63,10 @@ public class UserService {
* Returns all Guacamole users accessible to the user currently bound under * Returns all Guacamole users accessible to the user currently bound under
* the given LDAP connection. * the given LDAP connection.
* *
* @param user
* The AuthenticatedUser object associated with the user who is
* currently authenticated with Guacamole.
*
* @param ldapConnection * @param ldapConnection
* The current connection to the LDAP server, associated with the * The current connection to the LDAP server, associated with the
* current user. * current user.
@@ -81,16 +79,18 @@ public class UserService {
* @throws GuacamoleException * @throws GuacamoleException
* If an error occurs preventing retrieval of users. * If an error occurs preventing retrieval of users.
*/ */
public Map<String, User> getUsers(LdapNetworkConnection ldapConnection) public Map<String, User> getUsers(LDAPAuthenticatedUser user,
throws GuacamoleException { LdapNetworkConnection ldapConnection) throws GuacamoleException {
LDAPConfiguration config = user.getLDAPConfiguration();
// Retrieve all visible user objects // Retrieve all visible user objects
Collection<String> usernameAttrs = confService.getUsernameAttributes(); Collection<String> usernameAttrs = config.getUsernameAttributes();
Collection<String> attributes = new HashSet<>(usernameAttrs); Collection<String> attributes = new HashSet<>(usernameAttrs);
attributes.addAll(confService.getAttributes()); attributes.addAll(config.getAttributes());
List<Entry> results = queryService.search(ldapConnection, List<Entry> results = queryService.search(config, ldapConnection,
confService.getUserBaseDN(), config.getUserBaseDN(),
confService.getUserSearchFilter(), config.getUserSearchFilter(),
usernameAttrs, usernameAttrs,
null, null,
attributes); attributes);
@@ -124,6 +124,9 @@ public class UserService {
* is not enforced across the username attribute, it is possible that this * is not enforced across the username attribute, it is possible that this
* will return multiple DNs. * will return multiple DNs.
* *
* @param config
* The configuration of the LDAP server being queried.
*
* @param ldapConnection * @param ldapConnection
* The connection to the LDAP server to use when querying user DNs. * The connection to the LDAP server to use when querying user DNs.
* *
@@ -139,14 +142,14 @@ public class UserService {
* If an error occurs while querying the user DNs, or if the username * If an error occurs while querying the user DNs, or if the username
* attribute property cannot be parsed within guacamole.properties. * attribute property cannot be parsed within guacamole.properties.
*/ */
public List<Dn> getUserDNs(LdapNetworkConnection ldapConnection, public List<Dn> getUserDNs(LDAPConfiguration config, LdapNetworkConnection ldapConnection,
String username) throws GuacamoleException { String username) throws GuacamoleException {
// Retrieve user objects having a matching username // Retrieve user objects having a matching username
List<Entry> results = queryService.search(ldapConnection, List<Entry> results = queryService.search(config, ldapConnection,
confService.getUserBaseDN(), config.getUserBaseDN(),
confService.getUserSearchFilter(), config.getUserSearchFilter(),
confService.getUsernameAttributes(), config.getUsernameAttributes(),
username, username,
Collections.singletonList("dn")); Collections.singletonList("dn"));
@@ -164,6 +167,9 @@ public class UserService {
* or queried from the LDAP server, depending on how LDAP authentication * or queried from the LDAP server, depending on how LDAP authentication
* has been configured. * has been configured.
* *
* @param config
* The configuration of the LDAP server being queried.
*
* @param username * @param username
* The username of the user whose corresponding DN should be returned. * The username of the user whose corresponding DN should be returned.
* *
@@ -174,11 +180,11 @@ public class UserService {
* If required properties are missing, and thus the user DN cannot be * If required properties are missing, and thus the user DN cannot be
* determined. * determined.
*/ */
public Dn deriveUserDN(String username) public Dn deriveUserDN(LDAPConfiguration config, String username)
throws GuacamoleException { throws GuacamoleException {
// Pull username attributes from properties // Pull username attributes from properties
List<String> usernameAttributes = confService.getUsernameAttributes(); List<String> usernameAttributes = config.getUsernameAttributes();
// We need exactly one base DN to derive the user DN // We need exactly one base DN to derive the user DN
if (usernameAttributes.size() != 1) { if (usernameAttributes.size() != 1) {
@@ -193,7 +199,7 @@ public class UserService {
// Derive user DN from base DN // Derive user DN from base DN
try { try {
return new Dn(new Rdn(usernameAttributes.get(0), username), return new Dn(new Rdn(usernameAttributes.get(0), username),
confService.getUserBaseDN()); config.getUserBaseDN());
} }
catch (LdapInvalidAttributeValueException | LdapInvalidDnException e) { catch (LdapInvalidAttributeValueException | LdapInvalidDnException e) {
throw new GuacamoleServerException("Error trying to derive user DN.", e); throw new GuacamoleServerException("Error trying to derive user DN.", e);