GUAC-1115: Move LDAP connection management into own service.

This commit is contained in:
Michael Jumper
2015-10-23 16:03:53 -07:00
parent 00bf24791f
commit bd497c40b1
3 changed files with 157 additions and 101 deletions

View File

@@ -25,8 +25,6 @@ package org.glyptodon.guacamole.auth.ldap;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.novell.ldap.LDAPConnection;
import com.novell.ldap.LDAPException;
import java.io.UnsupportedEncodingException;
import java.util.List;
import org.glyptodon.guacamole.auth.ldap.user.AuthenticatedUser;
import org.glyptodon.guacamole.auth.ldap.user.UserContext;
@@ -51,6 +49,12 @@ public class AuthenticationProviderService {
*/
private final Logger logger = LoggerFactory.getLogger(AuthenticationProviderService.class);
/**
* Service for creating and managing connections to LDAP servers.
*/
@Inject
private LDAPConnectionService ldapService;
/**
* Service for retrieving LDAP server configuration information.
*/
@@ -75,28 +79,6 @@ public class AuthenticationProviderService {
@Inject
private Provider<UserContext> userContextProvider;
/**
* Disconnects the given LDAP connection, logging any failure to do so
* appropriately.
*
* @param ldapConnection
* The LDAP connection to disconnect.
*/
private void disconnect(LDAPConnection ldapConnection) {
// Attempt disconnect
try {
ldapConnection.disconnect();
}
// Warn if disconnect unexpectedly fails
catch (LDAPException e) {
logger.warn("Unable to disconnect from LDAP server: {}", e.getMessage());
logger.debug("LDAP disconnect failed.", e);
}
}
/**
* Determines the DN which corresponds to the user having the given
* username. The DN will either be derived directly from the user base DN,
@@ -122,7 +104,7 @@ public class AuthenticationProviderService {
if (searchBindDN != null) {
// Create an LDAP connection using the search account
LDAPConnection searchConnection = bindAs(
LDAPConnection searchConnection = ldapService.bindAs(
searchBindDN,
confService.getSearchBindPassword()
);
@@ -147,7 +129,7 @@ public class AuthenticationProviderService {
// Always disconnect
finally {
disconnect(searchConnection);
ldapService.disconnect(searchConnection);
}
}
@@ -157,78 +139,6 @@ public class AuthenticationProviderService {
}
/**
* Binds to the LDAP server using the provided user DN and password.
*
* @param userDN
* The DN of the user to bind as, or null to bind anonymously.
*
* @param password
* The password to use when binding as the specified user, or null to
* attempt to bind without a password.
*
* @return
* A bound LDAP connection, or null if the connection could not be
* bound.
*
* @throws GuacamoleException
* If an error occurs while binding to the LDAP server.
*/
private LDAPConnection bindAs(String userDN, String password)
throws GuacamoleException {
LDAPConnection ldapConnection;
// Connect to LDAP server
try {
ldapConnection = new LDAPConnection();
ldapConnection.connect(
confService.getServerHostname(),
confService.getServerPort()
);
}
catch (LDAPException e) {
logger.error("Unable to connect to LDAP server: {}", e.getMessage());
logger.debug("Failed to connect to LDAP server.", e);
return null;
}
// Bind using provided credentials
try {
byte[] passwordBytes;
try {
// Convert password into corresponding byte array
if (password != null)
passwordBytes = password.getBytes("UTF-8");
else
passwordBytes = null;
}
catch (UnsupportedEncodingException e) {
logger.error("Unexpected lack of support for UTF-8: {}", e.getMessage());
logger.debug("Support for UTF-8 (as required by Java spec) not found.", e);
disconnect(ldapConnection);
return null;
}
// Bind as user
ldapConnection.bind(LDAPConnection.LDAP_V3, userDN, passwordBytes);
}
// Disconnect if an error occurs during bind
catch (LDAPException e) {
logger.debug("LDAP bind failed.", e);
disconnect(ldapConnection);
return null;
}
return ldapConnection;
}
/**
* Binds to the LDAP server using the provided Guacamole credentials. The
* DN of the user is derived using the LDAP configuration properties
@@ -272,7 +182,7 @@ public class AuthenticationProviderService {
}
// Bind using user's DN
return bindAs(userDN, password);
return ldapService.bindAs(userDN, password);
}
@@ -320,7 +230,7 @@ public class AuthenticationProviderService {
// Always disconnect
finally {
disconnect(ldapConnection);
ldapService.disconnect(ldapConnection);
}
}
@@ -359,7 +269,7 @@ public class AuthenticationProviderService {
// Always disconnect
finally {
disconnect(ldapConnection);
ldapService.disconnect(ldapConnection);
}
}

View File

@@ -81,6 +81,7 @@ public class LDAPAuthenticationProviderModule extends AbstractModule {
bind(ConfigurationService.class);
bind(ConnectionService.class);
bind(EscapingService.class);
bind(LDAPConnectionService.class);
bind(UserService.class);
}

View File

@@ -0,0 +1,145 @@
/*
* Copyright (C) 2015 Glyptodon LLC
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package org.glyptodon.guacamole.auth.ldap;
import com.google.inject.Inject;
import com.novell.ldap.LDAPConnection;
import com.novell.ldap.LDAPException;
import java.io.UnsupportedEncodingException;
import org.glyptodon.guacamole.GuacamoleException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Service for creating and managing connections to LDAP servers.
*
* @author Michael Jumper
*/
public class LDAPConnectionService {
/**
* Logger for this class.
*/
private final Logger logger = LoggerFactory.getLogger(LDAPConnectionService.class);
/**
* Service for retrieving LDAP server configuration information.
*/
@Inject
private ConfigurationService confService;
/**
* Binds to the LDAP server using the provided user DN and password.
*
* @param userDN
* The DN of the user to bind as, or null to bind anonymously.
*
* @param password
* The password to use when binding as the specified user, or null to
* attempt to bind without a password.
*
* @return
* A bound LDAP connection, or null if the connection could not be
* bound.
*
* @throws GuacamoleException
* If an error occurs while binding to the LDAP server.
*/
public LDAPConnection bindAs(String userDN, String password)
throws GuacamoleException {
LDAPConnection ldapConnection;
// Connect to LDAP server
try {
ldapConnection = new LDAPConnection();
ldapConnection.connect(
confService.getServerHostname(),
confService.getServerPort()
);
}
catch (LDAPException e) {
logger.error("Unable to connect to LDAP server: {}", e.getMessage());
logger.debug("Failed to connect to LDAP server.", e);
return null;
}
// Bind using provided credentials
try {
byte[] passwordBytes;
try {
// Convert password into corresponding byte array
if (password != null)
passwordBytes = password.getBytes("UTF-8");
else
passwordBytes = null;
}
catch (UnsupportedEncodingException e) {
logger.error("Unexpected lack of support for UTF-8: {}", e.getMessage());
logger.debug("Support for UTF-8 (as required by Java spec) not found.", e);
disconnect(ldapConnection);
return null;
}
// Bind as user
ldapConnection.bind(LDAPConnection.LDAP_V3, userDN, passwordBytes);
}
// Disconnect if an error occurs during bind
catch (LDAPException e) {
logger.debug("LDAP bind failed.", e);
disconnect(ldapConnection);
return null;
}
return ldapConnection;
}
/**
* Disconnects the given LDAP connection, logging any failure to do so
* appropriately.
*
* @param ldapConnection
* The LDAP connection to disconnect.
*/
public void disconnect(LDAPConnection ldapConnection) {
// Attempt disconnect
try {
ldapConnection.disconnect();
}
// Warn if disconnect unexpectedly fails
catch (LDAPException e) {
logger.warn("Unable to disconnect from LDAP server: {}", e.getMessage());
logger.debug("LDAP disconnect failed.", e);
}
}
}