From 242cfbaf852b4380395103b8ca8e574cf30c323f Mon Sep 17 00:00:00 2001 From: Nick Couchman Date: Sat, 18 Mar 2017 11:08:56 -0400 Subject: [PATCH] GUACAMOLE-243: Finish up changes to deal with LDAP referrals, both in UserServer and ConnectionServer classes, along with global changes in LDAPConnectionService class. --- .../auth/ldap/LDAPConnectionService.java | 7 +- .../ldap/connection/ConnectionService.java | 118 +++++++++++------- .../guacamole/auth/ldap/user/UserService.java | 28 ++++- 3 files changed, 104 insertions(+), 49 deletions(-) diff --git a/extensions/guacamole-auth-ldap/src/main/java/org/apache/guacamole/auth/ldap/LDAPConnectionService.java b/extensions/guacamole-auth-ldap/src/main/java/org/apache/guacamole/auth/ldap/LDAPConnectionService.java index c3b2e12fd..82e6ca5af 100644 --- a/extensions/guacamole-auth-ldap/src/main/java/org/apache/guacamole/auth/ldap/LDAPConnectionService.java +++ b/extensions/guacamole-auth-ldap/src/main/java/org/apache/guacamole/auth/ldap/LDAPConnectionService.java @@ -118,13 +118,16 @@ public class LDAPConnectionService { if (ldapConstraints == null) ldapConstraints = new LDAPConstraints(); - // Set whether or not we follow referrals, and max hops + // Set whether or not we follow referrals ldapConstraints.setReferralFollowing(confService.getFollowReferrals()); - String refAuthMethod = confService.getReferralAuthentication(); + // If the referral auth method is set to bind, we set it using the existing + // username and password. + String refAuthMethod = confService.getReferralAuthentication(); if (refAuthMethod != null && refAuthMethod.equals("bind")) ldapConstraints.setReferralHandler(new ReferralAuthHandler(userDN, password)); + // Set the maximum number of referrals we follow ldapConstraints.setHopLimit(confService.getMaxReferralHops()); // Set timelimit to wait for LDAP operations, converting to ms diff --git a/extensions/guacamole-auth-ldap/src/main/java/org/apache/guacamole/auth/ldap/connection/ConnectionService.java b/extensions/guacamole-auth-ldap/src/main/java/org/apache/guacamole/auth/ldap/connection/ConnectionService.java index eea1a95ac..7f0634c93 100644 --- a/extensions/guacamole-auth-ldap/src/main/java/org/apache/guacamole/auth/ldap/connection/ConnectionService.java +++ b/extensions/guacamole-auth-ldap/src/main/java/org/apache/guacamole/auth/ldap/connection/ConnectionService.java @@ -24,6 +24,7 @@ import com.novell.ldap.LDAPAttribute; import com.novell.ldap.LDAPConnection; import com.novell.ldap.LDAPEntry; import com.novell.ldap.LDAPException; +import com.novell.ldap.LDAPReferralException; import com.novell.ldap.LDAPSearchResults; import java.util.Collections; import java.util.Enumeration; @@ -129,62 +130,80 @@ public class ConnectionService { Map connections = new HashMap(); while (results.hasMore()) { - LDAPEntry entry = results.next(); + try { - // Get common name (CN) - LDAPAttribute cn = entry.getAttribute("cn"); - if (cn == null) { - logger.warn("guacConfigGroup is missing a cn."); - continue; - } + LDAPEntry entry = results.next(); - // Get associated protocol - LDAPAttribute protocol = entry.getAttribute("guacConfigProtocol"); - if (protocol == null) { - logger.warn("guacConfigGroup \"{}\" is missing the " - + "required \"guacConfigProtocol\" attribute.", - cn.getStringValue()); - continue; - } + // Get common name (CN) + LDAPAttribute cn = entry.getAttribute("cn"); + if (cn == null) { + logger.warn("guacConfigGroup is missing a cn."); + continue; + } - // Set protocol - GuacamoleConfiguration config = new GuacamoleConfiguration(); - config.setProtocol(protocol.getStringValue()); + // Get associated protocol + LDAPAttribute protocol = entry.getAttribute("guacConfigProtocol"); + if (protocol == null) { + logger.warn("guacConfigGroup \"{}\" is missing the " + + "required \"guacConfigProtocol\" attribute.", + cn.getStringValue()); + continue; + } - // Get parameters, if any - LDAPAttribute parameterAttribute = entry.getAttribute("guacConfigParameter"); - if (parameterAttribute != null) { + // Set protocol + GuacamoleConfiguration config = new GuacamoleConfiguration(); + config.setProtocol(protocol.getStringValue()); - // For each parameter - Enumeration parameters = parameterAttribute.getStringValues(); - while (parameters.hasMoreElements()) { + // Get parameters, if any + LDAPAttribute parameterAttribute = entry.getAttribute("guacConfigParameter"); + if (parameterAttribute != null) { - String parameter = (String) parameters.nextElement(); + // For each parameter + Enumeration parameters = parameterAttribute.getStringValues(); + while (parameters.hasMoreElements()) { - // Parse parameter - int equals = parameter.indexOf('='); - if (equals != -1) { + String parameter = (String) parameters.nextElement(); - // Parse name - String name = parameter.substring(0, equals); - String value = parameter.substring(equals+1); + // Parse parameter + int equals = parameter.indexOf('='); + if (equals != -1) { - config.setParameter(name, value); + // Parse name + String name = parameter.substring(0, equals); + String value = parameter.substring(equals+1); + + config.setParameter(name, value); + + } } } + // Filter the configuration, substituting all defined tokens + tokenFilter.filterValues(config.getParameters()); + + // Store connection using cn for both identifier and name + String name = cn.getStringValue(); + Connection connection = new SimpleConnection(name, name, config); + connection.setParentIdentifier(LDAPAuthenticationProvider.ROOT_CONNECTION_GROUP); + connections.put(name, connection); + } - // Filter the configuration, substituting all defined tokens - tokenFilter.filterValues(config.getParameters()); - - // Store connection using cn for both identifier and name - String name = cn.getStringValue(); - Connection connection = new SimpleConnection(name, name, config); - connection.setParentIdentifier(LDAPAuthenticationProvider.ROOT_CONNECTION_GROUP); - connections.put(name, connection); + // Deal with issues following LDAP referrals + catch (LDAPReferralException e) { + if (confService.getFollowReferrals()) { + logger.error("Could not follow referral.", e.getMessage()); + logger.debug("Error encountered trying to follow referral.", e); + throw new GuacamoleServerException("Could not follow LDAP referral.", e); + } + else { + logger.warn("Given a referral, but referrals are disabled.", e.getMessage()); + logger.debug("Got a referral, but configured to not follow them.", e); + continue; + } + } } @@ -251,8 +270,23 @@ public class ConnectionService { // The guacConfig group uses the seeAlso attribute to refer // to these other groups while (userRoleGroupResults.hasMore()) { - LDAPEntry entry = userRoleGroupResults.next(); - connectionSearchFilter.append("(seeAlso=").append(escapingService.escapeLDAPSearchFilter(entry.getDN())).append(")"); + try { + LDAPEntry entry = userRoleGroupResults.next(); + connectionSearchFilter.append("(seeAlso=").append(escapingService.escapeLDAPSearchFilter(entry.getDN())).append(")"); + } + + catch (LDAPReferralException e) { + if (confService.getFollowReferrals()) { + logger.error("Could not follow referral.", e.getMessage()); + logger.debug("Error encountered trying to follow referral.", e); + throw new GuacamoleServerException("Could not follow LDAP referral.", e); + } + else { + logger.warn("Given a referral, but referrals are disabled.", e.getMessage()); + logger.debug("Got a referral, but configured to not follow them.", e); + continue; + } + } } } diff --git a/extensions/guacamole-auth-ldap/src/main/java/org/apache/guacamole/auth/ldap/user/UserService.java b/extensions/guacamole-auth-ldap/src/main/java/org/apache/guacamole/auth/ldap/user/UserService.java index 087365f1b..74d65c418 100644 --- a/extensions/guacamole-auth-ldap/src/main/java/org/apache/guacamole/auth/ldap/user/UserService.java +++ b/extensions/guacamole-auth-ldap/src/main/java/org/apache/guacamole/auth/ldap/user/UserService.java @@ -125,15 +125,17 @@ public class UserService { logger.warn("Possibly ambiguous user account: \"{}\".", identifier); } + + // Deal with errors trying to follow referrals catch (LDAPReferralException e) { if (confService.getFollowReferrals()) { logger.error("Could not follow referral.", e.getMessage()); logger.debug("Error encountered trying to follow referral.", e); - throw new GuacamoleException("Could not follow LDAP referral."); + throw new GuacamoleServerException("Could not follow LDAP referral.", e); } else { - logger.warn("Encountered a referral, but not following it.", e.getMessage()); - logger.debug("Got a referral, but not configured to follow it.", e); + logger.warn("Given a referral, but referrals are disabled.", e.getMessage()); + logger.debug("Got a referral, but configured to not follow them.", e); continue; } } @@ -284,8 +286,24 @@ public class UserService { // Add all DNs for found users while (results.hasMore()) { - LDAPEntry entry = results.next(); - userDNs.add(entry.getDN()); + try { + LDAPEntry entry = results.next(); + userDNs.add(entry.getDN()); + } + + // Deal with errors following referrals + catch (LDAPReferralException e) { + if (confService.getFollowReferrals()) { + logger.error("Error trying to follow a referral.", e.getMessage()); + logger.debug("Encountered an error trying to follow a referral.", e); + throw new GuacamoleServerException("Failed while trying to follow referrals.", e); + } + else { + logger.warn("Given a referral, not following it.", e.getMessage()); + logger.debug("Given a referral, but configured to not follow them.", e); + continue; + } + } } // Return all discovered DNs (if any)