GUACAMOLE-944: Merge support for arbitrary, non-DN search usernames.

This commit is contained in:
Mike Jumper
2021-05-30 17:11:56 -07:00
committed by GitHub
4 changed files with 31 additions and 23 deletions

View File

@@ -119,18 +119,19 @@ public class AuthenticationProviderService {
// 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
Dn searchBindDN = confService.getSearchBindDN(); String searchBindLogon = confService.getSearchBindDN();
if (searchBindDN != 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(
searchBindDN, searchBindLogon,
confService.getSearchBindPassword() confService.getSearchBindPassword()
); );
// Warn of failure to find // Warn of failure to find
if (searchConnection == null) { if (searchConnection == null) {
logger.error("Unable to bind using search DN \"{}\"", searchBindDN); logger.error("Unable to bind using search DN \"{}\"",
searchBindLogon);
return null; return null;
} }
@@ -203,7 +204,8 @@ public class AuthenticationProviderService {
} }
// Attempt bind // Attempt bind
LdapNetworkConnection ldapConnection = ldapService.bindAs(bindDn, password); LdapNetworkConnection ldapConnection =
ldapService.bindAs(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);
@@ -315,7 +317,8 @@ public class AuthenticationProviderService {
if (authenticatedUser instanceof LDAPAuthenticatedUser) { if (authenticatedUser instanceof LDAPAuthenticatedUser) {
Dn bindDn = ((LDAPAuthenticatedUser) authenticatedUser).getBindDn(); Dn bindDn = ((LDAPAuthenticatedUser) authenticatedUser).getBindDn();
LdapNetworkConnection ldapConnection = ldapService.bindAs(bindDn, credentials.getPassword()); LdapNetworkConnection ldapConnection =
ldapService.bindAs(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.",

View File

@@ -239,11 +239,11 @@ public class LDAPConnectionService {
* bound. * bound.
*/ */
private LdapNetworkConnection bindAs(LdapNetworkConnection ldapConnection, private LdapNetworkConnection bindAs(LdapNetworkConnection ldapConnection,
Dn userDN, String password) { String bindUser, String password) {
// Add credentials to existing config // Add credentials to existing config
LdapConnectionConfig config = ldapConnection.getConfig(); LdapConnectionConfig config = ldapConnection.getConfig();
config.setName(userDN.getName()); config.setName(bindUser);
config.setCredentials(password); config.setCredentials(password);
try { try {
@@ -255,7 +255,8 @@ public class LDAPConnectionService {
// only at the debug level (such failures are expected) // only at the debug level (such failures are expected)
catch (LdapAuthenticationException e) { catch (LdapAuthenticationException e) {
ldapConnection.close(); ldapConnection.close();
logger.debug("Bind attempt with LDAP server as user \"{}\" failed.", userDN, e); logger.debug("Bind attempt with LDAP server as user \"{}\" failed.",
bindUser, e);
return null; return null;
} }
@@ -264,7 +265,8 @@ public class LDAPConnectionService {
catch (LdapException e) { catch (LdapException e) {
ldapConnection.close(); ldapConnection.close();
logger.error("Binding with the LDAP server at \"{}\" as user " logger.error("Binding with the LDAP server at \"{}\" as user "
+ "\"{}\" failed: {}", config.getLdapHost(), userDN, e.getMessage()); + "\"{}\" failed: {}", config.getLdapHost(), bindUser,
e.getMessage());
logger.debug("Unable to bind to LDAP server.", e); logger.debug("Unable to bind to LDAP server.", e);
return null; return null;
} }
@@ -318,7 +320,7 @@ public class LDAPConnectionService {
} }
// Bind using username/password from existing connection // Bind using username/password from existing connection
return bindAs(ldapConnection, userDN, password); return bindAs(ldapConnection, userDN.getName(), password);
} }
@@ -327,8 +329,8 @@ 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 userDN * @param bindUser
* The DN 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.
* *
* @param password * @param password
* The password to use when binding as the specified user, or null to * The password to use when binding as the specified user, or null to
@@ -342,9 +344,9 @@ 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(Dn userDN, String password) public LdapNetworkConnection bindAs(String bindUser, String password)
throws GuacamoleException { throws GuacamoleException {
return bindAs(createLDAPConnection(), userDN, password); return bindAs(createLDAPConnection(), bindUser, password);
} }
/** /**

View File

@@ -171,7 +171,7 @@ public class ConfigurationService {
} }
/** /**
* Returns the DN that should be used when searching for the DNs of users * 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 * attempting to authenticate. If no such search should be performed, null
* is returned. * is returned.
* *
@@ -183,7 +183,7 @@ public class ConfigurationService {
* @throws GuacamoleException * @throws GuacamoleException
* If guacamole.properties cannot be parsed. * If guacamole.properties cannot be parsed.
*/ */
public Dn getSearchBindDN() throws GuacamoleException { public String getSearchBindDN() throws GuacamoleException {
return environment.getProperty( return environment.getProperty(
LDAPGuacamoleProperties.LDAP_SEARCH_BIND_DN LDAPGuacamoleProperties.LDAP_SEARCH_BIND_DN
); );

View File

@@ -128,13 +128,16 @@ public class LDAPGuacamoleProperties {
}; };
/** /**
* The DN of the user that the LDAP authentication should bind as when * The user that the LDAP extension should bind as when searching for the
* searching for the user accounts of users attempting to log in. If not * accounts of users attempting to log in. The format of this parameter
* specified, the DNs of users attempting to log in will be derived from * will vary based on the LDAP server implementation - often it is expected
* the LDAP_BASE_DN and LDAP_USERNAME_ATTRIBUTE directly. * to be in full LDAP DN format; however various LDAP server implementations
* allow this to be in other formats (e.g. Active Directory allows
* User Principal Name, or UPN, format). For this reason the configuration
* allows this to be any string.
*/ */
public static final LdapDnGuacamoleProperty LDAP_SEARCH_BIND_DN = public static final StringGuacamoleProperty LDAP_SEARCH_BIND_DN =
new LdapDnGuacamoleProperty() { new StringGuacamoleProperty() {
@Override @Override
public String getName() { return "ldap-search-bind-dn"; } public String getName() { return "ldap-search-bind-dn"; }