mirror of
https://github.com/gyurix1968/guacamole-client.git
synced 2025-10-27 15:13:07 +00:00
GUACAMOLE-524: Merge allow user attributes to be used as tokens.
This commit is contained in:
@@ -79,6 +79,7 @@ public class ModeledAuthenticatedUser extends RemoteAuthenticatedUser {
|
|||||||
super(authenticatedUser.getAuthenticationProvider(), authenticatedUser.getCredentials());
|
super(authenticatedUser.getAuthenticationProvider(), authenticatedUser.getCredentials());
|
||||||
this.modelAuthenticationProvider = modelAuthenticationProvider;
|
this.modelAuthenticationProvider = modelAuthenticationProvider;
|
||||||
this.user = user;
|
this.user = user;
|
||||||
|
super.setAttributes(authenticatedUser.getAttributes());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -93,7 +94,7 @@ public class ModeledAuthenticatedUser extends RemoteAuthenticatedUser {
|
|||||||
* A ModeledUser object which is backed by the data associated with
|
* A ModeledUser object which is backed by the data associated with
|
||||||
* this user in the database.
|
* this user in the database.
|
||||||
*
|
*
|
||||||
* @param credentials
|
* @param credentials
|
||||||
* The credentials given by the user when they authenticated.
|
* The credentials given by the user when they authenticated.
|
||||||
*/
|
*/
|
||||||
public ModeledAuthenticatedUser(AuthenticationProvider authenticationProvider,
|
public ModeledAuthenticatedUser(AuthenticationProvider authenticationProvider,
|
||||||
@@ -107,7 +108,7 @@ public class ModeledAuthenticatedUser extends RemoteAuthenticatedUser {
|
|||||||
* Returns a ModeledUser object which is backed by the data associated with
|
* Returns a ModeledUser object which is backed by the data associated with
|
||||||
* this user within the database.
|
* this user within the database.
|
||||||
*
|
*
|
||||||
* @return
|
* @return
|
||||||
* A ModeledUser object which is backed by the data associated with
|
* A ModeledUser object which is backed by the data associated with
|
||||||
* this user in the database.
|
* this user in the database.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -19,6 +19,8 @@
|
|||||||
|
|
||||||
package org.apache.guacamole.auth.jdbc.user;
|
package org.apache.guacamole.auth.jdbc.user;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
@@ -67,6 +69,21 @@ public abstract class RemoteAuthenticatedUser implements AuthenticatedUser {
|
|||||||
*/
|
*/
|
||||||
private static final Pattern X_FORWARDED_FOR = Pattern.compile("^" + IP_ADDRESS_REGEX + "(, " + IP_ADDRESS_REGEX + ")*$");
|
private static final Pattern X_FORWARDED_FOR = Pattern.compile("^" + IP_ADDRESS_REGEX + "(, " + IP_ADDRESS_REGEX + ")*$");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Arbitrary attributes associated with this RemoteAuthenticatedUser object.
|
||||||
|
*/
|
||||||
|
private Map<String, String> attributes = new HashMap<String, String>();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<String, String> getAttributes() {
|
||||||
|
return attributes;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setAttributes(Map<String, String> attributes) {
|
||||||
|
this.attributes = attributes;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Derives the remote host of the authenticating user from the given
|
* Derives the remote host of the authenticating user from the given
|
||||||
* credentials object. The remote host is derived from X-Forwarded-For
|
* credentials object. The remote host is derived from X-Forwarded-For
|
||||||
@@ -98,7 +115,7 @@ public abstract class RemoteAuthenticatedUser implements AuthenticatedUser {
|
|||||||
return request.getRemoteAddr();
|
return request.getRemoteAddr();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new RemoteAuthenticatedUser, deriving the associated remote
|
* Creates a new RemoteAuthenticatedUser, deriving the associated remote
|
||||||
* host from the given credentials.
|
* host from the given credentials.
|
||||||
@@ -106,7 +123,7 @@ public abstract class RemoteAuthenticatedUser implements AuthenticatedUser {
|
|||||||
* @param authenticationProvider
|
* @param authenticationProvider
|
||||||
* The AuthenticationProvider that has authenticated the given user.
|
* The AuthenticationProvider that has authenticated the given user.
|
||||||
*
|
*
|
||||||
* @param credentials
|
* @param credentials
|
||||||
* The credentials given by the user when they authenticated.
|
* The credentials given by the user when they authenticated.
|
||||||
*/
|
*/
|
||||||
public RemoteAuthenticatedUser(AuthenticationProvider authenticationProvider,
|
public RemoteAuthenticatedUser(AuthenticationProvider authenticationProvider,
|
||||||
|
|||||||
@@ -21,11 +21,18 @@ package org.apache.guacamole.auth.ldap;
|
|||||||
|
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
import com.google.inject.Provider;
|
import com.google.inject.Provider;
|
||||||
|
import com.novell.ldap.LDAPAttribute;
|
||||||
|
import com.novell.ldap.LDAPAttributeSet;
|
||||||
import com.novell.ldap.LDAPConnection;
|
import com.novell.ldap.LDAPConnection;
|
||||||
|
import com.novell.ldap.LDAPEntry;
|
||||||
|
import com.novell.ldap.LDAPException;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import org.apache.guacamole.auth.ldap.user.AuthenticatedUser;
|
import org.apache.guacamole.auth.ldap.user.AuthenticatedUser;
|
||||||
import org.apache.guacamole.auth.ldap.user.UserContext;
|
import org.apache.guacamole.auth.ldap.user.UserContext;
|
||||||
import org.apache.guacamole.GuacamoleException;
|
import org.apache.guacamole.GuacamoleException;
|
||||||
|
import org.apache.guacamole.GuacamoleServerException;
|
||||||
import org.apache.guacamole.auth.ldap.user.UserService;
|
import org.apache.guacamole.auth.ldap.user.UserService;
|
||||||
import org.apache.guacamole.net.auth.Credentials;
|
import org.apache.guacamole.net.auth.Credentials;
|
||||||
import org.apache.guacamole.net.auth.credentials.CredentialsInfo;
|
import org.apache.guacamole.net.auth.credentials.CredentialsInfo;
|
||||||
@@ -189,7 +196,8 @@ public class AuthenticationProviderService {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns an AuthenticatedUser representing the user authenticated by the
|
* Returns an AuthenticatedUser representing the user authenticated by the
|
||||||
* given credentials.
|
* given credentials. Also adds custom LDAP attributes to the
|
||||||
|
* AuthenticatedUser.
|
||||||
*
|
*
|
||||||
* @param credentials
|
* @param credentials
|
||||||
* The credentials to use for authentication.
|
* The credentials to use for authentication.
|
||||||
@@ -221,14 +229,16 @@ public class AuthenticationProviderService {
|
|||||||
throw new GuacamoleInvalidCredentialsException("Permission denied.", CredentialsInfo.USERNAME_PASSWORD);
|
throw new GuacamoleInvalidCredentialsException("Permission denied.", CredentialsInfo.USERNAME_PASSWORD);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
||||||
// Return AuthenticatedUser if bind succeeds
|
// Return AuthenticatedUser if bind succeeds
|
||||||
AuthenticatedUser authenticatedUser = authenticatedUserProvider.get();
|
AuthenticatedUser authenticatedUser = authenticatedUserProvider.get();
|
||||||
authenticatedUser.init(credentials);
|
authenticatedUser.init(credentials);
|
||||||
|
|
||||||
|
// Set attributes
|
||||||
|
authenticatedUser.setAttributes(getLDAPAttributes(ldapConnection, credentials.getUsername()));
|
||||||
|
|
||||||
return authenticatedUser;
|
return authenticatedUser;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Always disconnect
|
// Always disconnect
|
||||||
finally {
|
finally {
|
||||||
ldapService.disconnect(ldapConnection);
|
ldapService.disconnect(ldapConnection);
|
||||||
@@ -236,6 +246,58 @@ public class AuthenticationProviderService {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns all custom LDAP attributes on the user currently bound under
|
||||||
|
* the given LDAP connection. The custom attributes are specified in
|
||||||
|
* guacamole.properties.
|
||||||
|
*
|
||||||
|
* @param ldapConnection
|
||||||
|
* LDAP connection to find the custom LDAP attributes.
|
||||||
|
*
|
||||||
|
* @param username
|
||||||
|
* The username of the user whose attributes are queried.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* All attributes on the user currently bound under the
|
||||||
|
* given LDAP connection, as a map of attribute name to
|
||||||
|
* corresponding attribute value.
|
||||||
|
*
|
||||||
|
* @throws GuacamoleException
|
||||||
|
* If an error occurs retrieving the user DN or the attributes.
|
||||||
|
*/
|
||||||
|
private Map<String, String> getLDAPAttributes(LDAPConnection ldapConnection,
|
||||||
|
String username) throws GuacamoleException {
|
||||||
|
|
||||||
|
// Get attributes from configuration information
|
||||||
|
List<String> attrList = confService.getAttributes();
|
||||||
|
|
||||||
|
// If there are no attributes there is no reason to search LDAP
|
||||||
|
if (attrList == null || attrList.isEmpty())
|
||||||
|
return null;
|
||||||
|
|
||||||
|
// Build LDAP query parameters
|
||||||
|
String[] attrArray = attrList.toArray(new String[attrList.size()]);
|
||||||
|
String userDN = getUserBindDN(username);
|
||||||
|
|
||||||
|
Map<String, String> attrMap = new HashMap<String, String>();
|
||||||
|
try {
|
||||||
|
// Get LDAP attributes by querying LDAP
|
||||||
|
LDAPEntry userEntry = ldapConnection.read(userDN, attrArray);
|
||||||
|
LDAPAttributeSet attrSet = userEntry.getAttributeSet();
|
||||||
|
|
||||||
|
// Add each attribute into Map
|
||||||
|
for (Object attrObj : attrSet) {
|
||||||
|
LDAPAttribute attr = (LDAPAttribute)attrObj;
|
||||||
|
attrMap.put(attr.getName(), attr.getStringValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (LDAPException e) {
|
||||||
|
throw new GuacamoleServerException("Error while querying for User Attributes.", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
return attrMap;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a UserContext object initialized with data accessible to the
|
* Returns a UserContext object initialized with data accessible to the
|
||||||
* given AuthenticatedUser.
|
* given AuthenticatedUser.
|
||||||
|
|||||||
@@ -227,7 +227,7 @@ public class ConfigurationService {
|
|||||||
private int getMaxResults() throws GuacamoleException {
|
private int getMaxResults() throws GuacamoleException {
|
||||||
return environment.getProperty(
|
return environment.getProperty(
|
||||||
LDAPGuacamoleProperties.LDAP_MAX_SEARCH_RESULTS,
|
LDAPGuacamoleProperties.LDAP_MAX_SEARCH_RESULTS,
|
||||||
1000
|
1000
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -344,4 +344,19 @@ public class ConfigurationService {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns names for custom LDAP user attributes.
|
||||||
|
*
|
||||||
|
* @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
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -205,4 +205,14 @@ public class LDAPGuacamoleProperties {
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Custom attribute or attributes to query from Guacamole user's record in
|
||||||
|
* the LDAP directory.
|
||||||
|
*/
|
||||||
|
public static final StringListProperty LDAP_USER_ATTRIBUTES = new StringListProperty() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() { return "ldap-user-attributes"; }
|
||||||
|
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -295,4 +295,3 @@ public class ConnectionService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -20,6 +20,8 @@
|
|||||||
package org.apache.guacamole.auth.ldap.user;
|
package org.apache.guacamole.auth.ldap.user;
|
||||||
|
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
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;
|
||||||
@@ -42,6 +44,11 @@ public class AuthenticatedUser extends AbstractAuthenticatedUser {
|
|||||||
*/
|
*/
|
||||||
private Credentials credentials;
|
private Credentials credentials;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Arbitrary attributes associated with this AuthenticatedUser object.
|
||||||
|
*/
|
||||||
|
private Map<String, String> attributes = new HashMap<String, String>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes this AuthenticatedUser using the given credentials.
|
* Initializes this AuthenticatedUser using the given credentials.
|
||||||
*
|
*
|
||||||
@@ -53,6 +60,16 @@ public class AuthenticatedUser extends AbstractAuthenticatedUser {
|
|||||||
setIdentifier(credentials.getUsername());
|
setIdentifier(credentials.getUsername());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<String, String> getAttributes() {
|
||||||
|
return attributes;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setAttributes(Map<String, String> attributes) {
|
||||||
|
this.attributes = attributes;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public AuthenticationProvider getAuthenticationProvider() {
|
public AuthenticationProvider getAuthenticationProvider() {
|
||||||
return authProvider;
|
return authProvider;
|
||||||
|
|||||||
@@ -20,6 +20,7 @@
|
|||||||
package org.apache.guacamole.net.auth;
|
package org.apache.guacamole.net.auth;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -41,4 +42,14 @@ public abstract class AbstractAuthenticatedUser extends AbstractIdentifiable
|
|||||||
// Nothing to invalidate
|
// Nothing to invalidate
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<String, String> getAttributes() {
|
||||||
|
return Collections.<String, String>emptyMap();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setAttributes(Map<String, String> attributes) {
|
||||||
|
//do nothing
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ import java.util.Set;
|
|||||||
* A user of the Guacamole web application who has been authenticated by an
|
* A user of the Guacamole web application who has been authenticated by an
|
||||||
* AuthenticationProvider.
|
* AuthenticationProvider.
|
||||||
*/
|
*/
|
||||||
public interface AuthenticatedUser extends Identifiable {
|
public interface AuthenticatedUser extends Identifiable, Attributes {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The identifier reserved for representing a user that has authenticated
|
* The identifier reserved for representing a user that has authenticated
|
||||||
|
|||||||
@@ -21,6 +21,8 @@ package org.apache.guacamole.token;
|
|||||||
|
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
import org.apache.guacamole.net.auth.AuthenticatedUser;
|
import org.apache.guacamole.net.auth.AuthenticatedUser;
|
||||||
import org.apache.guacamole.net.auth.Credentials;
|
import org.apache.guacamole.net.auth.Credentials;
|
||||||
|
|
||||||
@@ -74,6 +76,11 @@ public class StandardTokens {
|
|||||||
*/
|
*/
|
||||||
private static final String TIME_FORMAT = "HHmmss";
|
private static final String TIME_FORMAT = "HHmmss";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The prefix of the arbitrary attribute tokens.
|
||||||
|
*/
|
||||||
|
public static final String ATTR_TOKEN_PREFIX = "GUAC_ATTR_";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This utility class should not be instantiated.
|
* This utility class should not be instantiated.
|
||||||
*/
|
*/
|
||||||
@@ -143,10 +150,11 @@ public class StandardTokens {
|
|||||||
* Adds tokens which are standardized by guacamole-ext to the given
|
* Adds tokens which are standardized by guacamole-ext to the given
|
||||||
* TokenFilter using the values from the given AuthenticatedUser object,
|
* TokenFilter using the values from the given AuthenticatedUser object,
|
||||||
* including any associated credentials. These standardized tokens include
|
* including any associated credentials. These standardized tokens include
|
||||||
* the current username (GUAC_USERNAME), password (GUAC_PASSWORD), and the
|
* the current username (GUAC_USERNAME), password (GUAC_PASSWORD), the
|
||||||
* server date and time (GUAC_DATE and GUAC_TIME respectively). If either
|
* server date and time (GUAC_DATE and GUAC_TIME respectively), and custom
|
||||||
* the username or password are not set within the given user or their
|
* user attributes. If either the username or password are not set within
|
||||||
* provided credentials, the corresponding token(s) will remain unset.
|
* the given user or their provided credentials, the corresponding token(s)
|
||||||
|
* will remain unset.
|
||||||
*
|
*
|
||||||
* @param filter
|
* @param filter
|
||||||
* The TokenFilter to add standard tokens to.
|
* The TokenFilter to add standard tokens to.
|
||||||
@@ -164,6 +172,33 @@ public class StandardTokens {
|
|||||||
// Add tokens specific to credentials
|
// Add tokens specific to credentials
|
||||||
addStandardTokens(filter, user.getCredentials());
|
addStandardTokens(filter, user.getCredentials());
|
||||||
|
|
||||||
|
// Add custom attribute tokens
|
||||||
|
addAttributeTokens(filter, user.getAttributes());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add attribute tokens to StandardTokens. These are arbitrary
|
||||||
|
* key/value pairs that may be configured by the various authentication
|
||||||
|
* extensions.
|
||||||
|
*
|
||||||
|
* @param filter
|
||||||
|
* The TokenFilter to add attribute tokens to.
|
||||||
|
*
|
||||||
|
* @param attributes
|
||||||
|
* The map of key/value pairs to add tokens for.
|
||||||
|
*/
|
||||||
|
public static void addAttributeTokens(TokenFilter filter,
|
||||||
|
Map<String, String> attributes) {
|
||||||
|
|
||||||
|
if (attributes != null) {
|
||||||
|
for (Map.Entry entry : attributes.entrySet()) {
|
||||||
|
String key = entry.getKey().toString();
|
||||||
|
String tokenName = ATTR_TOKEN_PREFIX + key.toUpperCase();
|
||||||
|
String tokenValue = entry.getValue().toString();
|
||||||
|
filter.setToken(tokenName, tokenValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user