mirror of
https://github.com/gyurix1968/guacamole-client.git
synced 2025-09-06 05:07:41 +00:00
GUACAMOLE-1239: Merge support for configuring username case-insensitivity.
This commit is contained in:
@@ -54,4 +54,25 @@ public class ConfigurationService {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if the usernames provided to the header authentication
|
||||||
|
* module should be treated as case-sensitive, or false if usernames
|
||||||
|
* should be treated as case-insensitive. This will default to the global
|
||||||
|
* Guacamole configuration for case-sensitivity, which defaults to true, but
|
||||||
|
* can be overridden for this extension, if desired.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* true if usernames should be treated as case-sensitive, otherwise
|
||||||
|
* false.
|
||||||
|
*
|
||||||
|
* @throws GuacamoleException
|
||||||
|
* If guacamole.properties cannot be parsed.
|
||||||
|
*/
|
||||||
|
public boolean getCaseSensitiveUsernames() throws GuacamoleException {
|
||||||
|
return environment.getProperty(
|
||||||
|
HTTPHeaderGuacamoleProperties.HTTP_AUTH_CASE_SENSITIVE_USERNAMES,
|
||||||
|
environment.getCaseSensitiveUsernames()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -19,7 +19,7 @@
|
|||||||
|
|
||||||
package org.apache.guacamole.auth.header;
|
package org.apache.guacamole.auth.header;
|
||||||
|
|
||||||
import org.apache.guacamole.properties.IntegerGuacamoleProperty;
|
import org.apache.guacamole.properties.BooleanGuacamoleProperty;
|
||||||
import org.apache.guacamole.properties.StringGuacamoleProperty;
|
import org.apache.guacamole.properties.StringGuacamoleProperty;
|
||||||
|
|
||||||
|
|
||||||
@@ -36,7 +36,7 @@ public class HTTPHeaderGuacamoleProperties {
|
|||||||
private HTTPHeaderGuacamoleProperties() {}
|
private HTTPHeaderGuacamoleProperties() {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The header used for HTTP header authentication.
|
* A property used to configure the header used for HTTP header authentication.
|
||||||
*/
|
*/
|
||||||
public static final StringGuacamoleProperty HTTP_AUTH_HEADER = new StringGuacamoleProperty() {
|
public static final StringGuacamoleProperty HTTP_AUTH_HEADER = new StringGuacamoleProperty() {
|
||||||
|
|
||||||
@@ -45,4 +45,16 @@ public class HTTPHeaderGuacamoleProperties {
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A property used to configure whether or not usernames within the header
|
||||||
|
* module should be treated as case-sensitive.
|
||||||
|
*/
|
||||||
|
public static final BooleanGuacamoleProperty HTTP_AUTH_CASE_SENSITIVE_USERNAMES =
|
||||||
|
new BooleanGuacamoleProperty() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() { return "http-auth-case-sensitive-usernames"; }
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -20,9 +20,13 @@
|
|||||||
package org.apache.guacamole.auth.header.user;
|
package org.apache.guacamole.auth.header.user;
|
||||||
|
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
|
import org.apache.guacamole.GuacamoleException;
|
||||||
|
import org.apache.guacamole.auth.header.ConfigurationService;
|
||||||
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;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An HTTP header implementation of AuthenticatedUser, associating a
|
* An HTTP header implementation of AuthenticatedUser, associating a
|
||||||
@@ -31,6 +35,11 @@ import org.apache.guacamole.net.auth.Credentials;
|
|||||||
*/
|
*/
|
||||||
public class AuthenticatedUser extends AbstractAuthenticatedUser {
|
public class AuthenticatedUser extends AbstractAuthenticatedUser {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Logger for this class.
|
||||||
|
*/
|
||||||
|
private static final Logger LOGGER = LoggerFactory.getLogger(AuthenticatedUser.class);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reference to the authentication provider associated with this
|
* Reference to the authentication provider associated with this
|
||||||
* authenticated user.
|
* authenticated user.
|
||||||
@@ -38,6 +47,12 @@ public class AuthenticatedUser extends AbstractAuthenticatedUser {
|
|||||||
@Inject
|
@Inject
|
||||||
private AuthenticationProvider authProvider;
|
private AuthenticationProvider authProvider;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Service for retrieving header configuration information.
|
||||||
|
*/
|
||||||
|
@Inject
|
||||||
|
private ConfigurationService confService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The credentials provided when this user was authenticated.
|
* The credentials provided when this user was authenticated.
|
||||||
*/
|
*/
|
||||||
@@ -58,6 +73,19 @@ public class AuthenticatedUser extends AbstractAuthenticatedUser {
|
|||||||
setIdentifier(username.toLowerCase());
|
setIdentifier(username.toLowerCase());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isCaseSensitive() {
|
||||||
|
try {
|
||||||
|
return confService.getCaseSensitiveUsernames();
|
||||||
|
}
|
||||||
|
catch (GuacamoleException e) {
|
||||||
|
LOGGER.error("Error when trying to retrieve header configuration: {}."
|
||||||
|
+ " Usernames comparison will be case-sensitive.", e);
|
||||||
|
LOGGER.debug("Exception caught when retrieving header configuration.", e);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public AuthenticationProvider getAuthenticationProvider() {
|
public AuthenticationProvider getAuthenticationProvider() {
|
||||||
return authProvider;
|
return authProvider;
|
||||||
|
@@ -19,6 +19,7 @@
|
|||||||
|
|
||||||
package org.apache.guacamole.auth.jdbc;
|
package org.apache.guacamole.auth.jdbc;
|
||||||
|
|
||||||
|
import com.google.inject.Inject;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@@ -56,6 +57,12 @@ public class HistoryTrackingConnection extends DelegatingConnection {
|
|||||||
*/
|
*/
|
||||||
private final ConnectionRecordMapper connectionRecordMapper;
|
private final ConnectionRecordMapper connectionRecordMapper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Guacamole server environment.
|
||||||
|
*/
|
||||||
|
@Inject
|
||||||
|
private JDBCEnvironment environment;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new HistoryConnection that wraps the given connection,
|
* Creates a new HistoryConnection that wraps the given connection,
|
||||||
* automatically creating a history record when the connection is
|
* automatically creating a history record when the connection is
|
||||||
@@ -98,7 +105,8 @@ public class HistoryTrackingConnection extends DelegatingConnection {
|
|||||||
connectionRecordModel.setConnectionName(this.getDelegateConnection().getName());
|
connectionRecordModel.setConnectionName(this.getDelegateConnection().getName());
|
||||||
|
|
||||||
// Insert the connection history record to mark the start of this connection
|
// Insert the connection history record to mark the start of this connection
|
||||||
connectionRecordMapper.insert(connectionRecordModel);
|
connectionRecordMapper.insert(connectionRecordModel,
|
||||||
|
environment.getCaseSensitiveUsernames());
|
||||||
|
|
||||||
// Include history record UUID as token
|
// Include history record UUID as token
|
||||||
ModeledConnectionRecord modeledRecord = new ModeledConnectionRecord(connectionRecordModel);
|
ModeledConnectionRecord modeledRecord = new ModeledConnectionRecord(connectionRecordModel);
|
||||||
|
@@ -39,10 +39,15 @@ public interface ActivityRecordMapper<ModelType> {
|
|||||||
* @param record
|
* @param record
|
||||||
* The activity record to insert.
|
* The activity record to insert.
|
||||||
*
|
*
|
||||||
|
* @param caseSensitive
|
||||||
|
* Whether or not string comparisons should be done in a case-sensitive
|
||||||
|
* manner.
|
||||||
|
*
|
||||||
* @return
|
* @return
|
||||||
* The number of rows inserted.
|
* The number of rows inserted.
|
||||||
*/
|
*/
|
||||||
int insert(@Param("record") ModelType record);
|
int insert(@Param("record") ModelType record,
|
||||||
|
@Param("caseSensitive") boolean caseSensitive);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates the given activity record in the database, assigning an end
|
* Updates the given activity record in the database, assigning an end
|
||||||
@@ -86,6 +91,10 @@ public interface ActivityRecordMapper<ModelType> {
|
|||||||
* @param limit
|
* @param limit
|
||||||
* The maximum number of records that should be returned.
|
* The maximum number of records that should be returned.
|
||||||
*
|
*
|
||||||
|
* @param caseSensitive
|
||||||
|
* Whether or not string comparisons should be done in a case-sensitive
|
||||||
|
* manner.
|
||||||
|
*
|
||||||
* @return
|
* @return
|
||||||
* The results of the search performed with the given parameters.
|
* The results of the search performed with the given parameters.
|
||||||
*/
|
*/
|
||||||
@@ -93,7 +102,8 @@ public interface ActivityRecordMapper<ModelType> {
|
|||||||
@Param("recordIdentifier") String recordIdentifier,
|
@Param("recordIdentifier") String recordIdentifier,
|
||||||
@Param("terms") Collection<ActivityRecordSearchTerm> terms,
|
@Param("terms") Collection<ActivityRecordSearchTerm> terms,
|
||||||
@Param("sortPredicates") List<ActivityRecordSortPredicate> sortPredicates,
|
@Param("sortPredicates") List<ActivityRecordSortPredicate> sortPredicates,
|
||||||
@Param("limit") int limit);
|
@Param("limit") int limit,
|
||||||
|
@Param("caseSensitive") boolean caseSensitive);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Searches for up to <code>limit</code> activity records that contain
|
* Searches for up to <code>limit</code> activity records that contain
|
||||||
@@ -133,6 +143,10 @@ public interface ActivityRecordMapper<ModelType> {
|
|||||||
* no groups are given, only permissions directly granted to the user
|
* no groups are given, only permissions directly granted to the user
|
||||||
* will be used.
|
* will be used.
|
||||||
*
|
*
|
||||||
|
* @param caseSensitive
|
||||||
|
* Whether or not string comparisons should be done in a case-sensitive
|
||||||
|
* manner.
|
||||||
|
*
|
||||||
* @return
|
* @return
|
||||||
* The results of the search performed with the given parameters.
|
* The results of the search performed with the given parameters.
|
||||||
*/
|
*/
|
||||||
@@ -142,6 +156,7 @@ public interface ActivityRecordMapper<ModelType> {
|
|||||||
@Param("terms") Collection<ActivityRecordSearchTerm> terms,
|
@Param("terms") Collection<ActivityRecordSearchTerm> terms,
|
||||||
@Param("sortPredicates") List<ActivityRecordSortPredicate> sortPredicates,
|
@Param("sortPredicates") List<ActivityRecordSortPredicate> sortPredicates,
|
||||||
@Param("limit") int limit,
|
@Param("limit") int limit,
|
||||||
@Param("effectiveGroups") Collection<String> effectiveGroups);
|
@Param("effectiveGroups") Collection<String> effectiveGroups,
|
||||||
|
@Param("caseSensitive") boolean caseSensitive);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -28,19 +28,20 @@ import java.util.HashMap;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import org.apache.guacamole.auth.jdbc.user.ModeledAuthenticatedUser;
|
|
||||||
import org.apache.guacamole.language.TranslatableGuacamoleClientOverrunException;
|
|
||||||
import org.apache.guacamole.language.TranslatableMessage;
|
|
||||||
import org.apache.guacamole.auth.jdbc.base.ModeledDirectoryObjectMapper;
|
|
||||||
import org.apache.guacamole.auth.jdbc.tunnel.GuacamoleTunnelService;
|
|
||||||
import org.apache.guacamole.GuacamoleClientException;
|
import org.apache.guacamole.GuacamoleClientException;
|
||||||
import org.apache.guacamole.GuacamoleException;
|
import org.apache.guacamole.GuacamoleException;
|
||||||
import org.apache.guacamole.GuacamoleSecurityException;
|
import org.apache.guacamole.GuacamoleSecurityException;
|
||||||
|
import org.apache.guacamole.auth.jdbc.JDBCEnvironment;
|
||||||
import org.apache.guacamole.auth.jdbc.base.ActivityRecordSearchTerm;
|
import org.apache.guacamole.auth.jdbc.base.ActivityRecordSearchTerm;
|
||||||
import org.apache.guacamole.auth.jdbc.base.ActivityRecordSortPredicate;
|
import org.apache.guacamole.auth.jdbc.base.ActivityRecordSortPredicate;
|
||||||
|
import org.apache.guacamole.auth.jdbc.user.ModeledAuthenticatedUser;
|
||||||
import org.apache.guacamole.auth.jdbc.base.ModeledChildDirectoryObjectService;
|
import org.apache.guacamole.auth.jdbc.base.ModeledChildDirectoryObjectService;
|
||||||
|
import org.apache.guacamole.auth.jdbc.base.ModeledDirectoryObjectMapper;
|
||||||
import org.apache.guacamole.auth.jdbc.permission.ConnectionPermissionMapper;
|
import org.apache.guacamole.auth.jdbc.permission.ConnectionPermissionMapper;
|
||||||
import org.apache.guacamole.auth.jdbc.permission.ObjectPermissionMapper;
|
import org.apache.guacamole.auth.jdbc.permission.ObjectPermissionMapper;
|
||||||
|
import org.apache.guacamole.auth.jdbc.tunnel.GuacamoleTunnelService;
|
||||||
|
import org.apache.guacamole.language.TranslatableGuacamoleClientOverrunException;
|
||||||
|
import org.apache.guacamole.language.TranslatableMessage;
|
||||||
import org.apache.guacamole.net.GuacamoleTunnel;
|
import org.apache.guacamole.net.GuacamoleTunnel;
|
||||||
import org.apache.guacamole.net.auth.Connection;
|
import org.apache.guacamole.net.auth.Connection;
|
||||||
import org.apache.guacamole.net.auth.ConnectionRecord;
|
import org.apache.guacamole.net.auth.ConnectionRecord;
|
||||||
@@ -86,6 +87,12 @@ public class ConnectionService extends ModeledChildDirectoryObjectService<Modele
|
|||||||
@Inject
|
@Inject
|
||||||
private Provider<ModeledConnection> connectionProvider;
|
private Provider<ModeledConnection> connectionProvider;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The server environment for retrieving configuration.
|
||||||
|
*/
|
||||||
|
@Inject
|
||||||
|
private JDBCEnvironment environment;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Service for creating and tracking tunnels.
|
* Service for creating and tracking tunnels.
|
||||||
*/
|
*/
|
||||||
@@ -486,14 +493,16 @@ public class ConnectionService extends ModeledChildDirectoryObjectService<Modele
|
|||||||
// Bypass permission checks if the user is privileged or has System-level audit permissions
|
// Bypass permission checks if the user is privileged or has System-level audit permissions
|
||||||
if (user.isPrivileged() || user.getUser().getEffectivePermissions().getSystemPermissions().hasPermission(SystemPermission.Type.AUDIT))
|
if (user.isPrivileged() || user.getUser().getEffectivePermissions().getSystemPermissions().hasPermission(SystemPermission.Type.AUDIT))
|
||||||
searchResults = connectionRecordMapper.search(identifier,
|
searchResults = connectionRecordMapper.search(identifier,
|
||||||
recordIdentifier, requiredContents, sortPredicates, limit);
|
recordIdentifier, requiredContents, sortPredicates, limit,
|
||||||
|
environment.getCaseSensitiveUsernames());
|
||||||
|
|
||||||
// Otherwise only return explicitly readable history records
|
// Otherwise only return explicitly readable history records
|
||||||
else
|
else
|
||||||
searchResults = connectionRecordMapper.searchReadable(identifier,
|
searchResults = connectionRecordMapper.searchReadable(identifier,
|
||||||
user.getUser().getModel(), recordIdentifier,
|
user.getUser().getModel(), recordIdentifier,
|
||||||
requiredContents, sortPredicates, limit,
|
requiredContents, sortPredicates, limit,
|
||||||
user.getEffectiveUserGroups());
|
user.getEffectiveUserGroups(),
|
||||||
|
environment.getCaseSensitiveUsernames());
|
||||||
|
|
||||||
return getObjectInstances(searchResults);
|
return getObjectInstances(searchResults);
|
||||||
|
|
||||||
|
@@ -19,7 +19,142 @@
|
|||||||
|
|
||||||
package org.apache.guacamole.auth.jdbc.permission;
|
package org.apache.guacamole.auth.jdbc.permission;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import org.apache.guacamole.auth.jdbc.base.EntityModel;
|
||||||
|
import org.apache.guacamole.net.auth.permission.ObjectPermission;
|
||||||
|
import org.apache.ibatis.annotations.Param;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Mapper for user permissions.
|
* Mapper for user permissions.
|
||||||
*/
|
*/
|
||||||
public interface UserPermissionMapper extends ObjectPermissionMapper {}
|
public interface UserPermissionMapper extends ObjectPermissionMapper {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deletes the given permissions from the database. If any permissions do
|
||||||
|
* not exist, they will be ignored.
|
||||||
|
*
|
||||||
|
* @param permissions
|
||||||
|
* The permissions to delete.
|
||||||
|
*
|
||||||
|
* @param caseSensitive
|
||||||
|
* Whether or not string comparisons for usernames will be done in a
|
||||||
|
* case-sensitive manner.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* The number of rows deleted.
|
||||||
|
*/
|
||||||
|
int delete(@Param("permissions") Collection<ObjectPermission.Type> permissions,
|
||||||
|
@Param("caseSensitive") boolean caseSensitive);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Inserts the given permissions into the database. If any permissions
|
||||||
|
* already exist, they will be ignored.
|
||||||
|
*
|
||||||
|
* @param permissions
|
||||||
|
* The permissions to insert.
|
||||||
|
*
|
||||||
|
* @param caseSensitive
|
||||||
|
* Whether or not string comparisons for usernames will be done in a
|
||||||
|
* case-sensitive manner.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* The number of rows inserted.
|
||||||
|
*/
|
||||||
|
int insert(@Param("permissions") Collection<ObjectPermission.Type> permissions,
|
||||||
|
@Param("caseSensitive") boolean caseSensitive);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves all permissions associated with the given entity (user or user
|
||||||
|
* group).
|
||||||
|
*
|
||||||
|
* @param entity
|
||||||
|
* The entity to retrieve permissions for.
|
||||||
|
*
|
||||||
|
* @param effectiveGroups
|
||||||
|
* The identifiers of all groups that should be taken into account
|
||||||
|
* when determining the permissions effectively granted to the user. If
|
||||||
|
* no groups are given, only permissions directly granted to the user
|
||||||
|
* will be used.
|
||||||
|
*
|
||||||
|
* @param caseSensitive
|
||||||
|
* Whether or not string comparisons for usernames will be done in a
|
||||||
|
* case-sensitive manner.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* All permissions associated with the given entity.
|
||||||
|
*/
|
||||||
|
Collection<ObjectPermission.Type> select(@Param("entity") EntityModel entity,
|
||||||
|
@Param("effectiveGroups") Collection<String> effectiveGroups,
|
||||||
|
@Param("caseSensitive") boolean caseSensitive);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the permission of the given type associated with the given
|
||||||
|
* entity and object, if it exists. If no such permission exists, null is
|
||||||
|
* returned.
|
||||||
|
*
|
||||||
|
* @param entity
|
||||||
|
* The entity to retrieve permissions for.
|
||||||
|
*
|
||||||
|
* @param type
|
||||||
|
* The type of permission to return.
|
||||||
|
*
|
||||||
|
* @param identifier
|
||||||
|
* The identifier of the object affected by the permission to return.
|
||||||
|
*
|
||||||
|
* @param effectiveGroups
|
||||||
|
* The identifiers of all groups that should be taken into account
|
||||||
|
* when determining the permissions effectively granted to the user. If
|
||||||
|
* no groups are given, only permissions directly granted to the user
|
||||||
|
* will be used.
|
||||||
|
*
|
||||||
|
* @param caseSensitive
|
||||||
|
* Whether or not string comparisons for usernames will be done in a
|
||||||
|
* case-sensitive manner.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* The requested permission, or null if no such permission is granted
|
||||||
|
* to the given entity for the given object.
|
||||||
|
*/
|
||||||
|
ObjectPermissionModel selectOne(@Param("entity") EntityModel entity,
|
||||||
|
@Param("type") ObjectPermission.Type type,
|
||||||
|
@Param("identifier") String identifier,
|
||||||
|
@Param("effectiveGroups") Collection<String> effectiveGroups,
|
||||||
|
@Param("caseSensitive") boolean caseSensitive);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the subset of the given identifiers for which the given entity
|
||||||
|
* has at least one of the given permissions.
|
||||||
|
*
|
||||||
|
* @param entity
|
||||||
|
* The entity to check permissions of.
|
||||||
|
*
|
||||||
|
* @param permissions
|
||||||
|
* The permissions to check. An identifier will be included in the
|
||||||
|
* resulting collection if at least one of these permissions is granted
|
||||||
|
* for the associated object
|
||||||
|
*
|
||||||
|
* @param identifiers
|
||||||
|
* The identifiers of the objects affected by the permissions being
|
||||||
|
* checked.
|
||||||
|
*
|
||||||
|
* @param effectiveGroups
|
||||||
|
* The identifiers of all groups that should be taken into account
|
||||||
|
* when determining the permissions effectively granted to the user. If
|
||||||
|
* no groups are given, only permissions directly granted to the user
|
||||||
|
* will be used.
|
||||||
|
*
|
||||||
|
* @param caseSensitive
|
||||||
|
* Whether or not string comparisons for usernames will be done in a
|
||||||
|
* case-sensitive manner.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* A collection containing the subset of identifiers for which at least
|
||||||
|
* one of the specified permissions is granted.
|
||||||
|
*/
|
||||||
|
Collection<String> selectAccessibleIdentifiers(@Param("entity") EntityModel entity,
|
||||||
|
@Param("permissions") Collection<ObjectPermission.Type> permissions,
|
||||||
|
@Param("identifiers") Collection<String> identifiers,
|
||||||
|
@Param("effectiveGroups") Collection<String> effectiveGroups,
|
||||||
|
@Param("caseSenstive") boolean caseSensitive);
|
||||||
|
|
||||||
|
}
|
||||||
|
@@ -131,16 +131,21 @@ public class PasswordPolicyService {
|
|||||||
* @return
|
* @return
|
||||||
* true if the given password matches any of the user's previous
|
* true if the given password matches any of the user's previous
|
||||||
* passwords, up to the specified limit, false otherwise.
|
* passwords, up to the specified limit, false otherwise.
|
||||||
|
*
|
||||||
|
* @throws GuacamoleException
|
||||||
|
* If an error occurs accessing environment information used for
|
||||||
|
* retrieving configuration values.
|
||||||
*/
|
*/
|
||||||
private boolean matchesPreviousPasswords(String password, String username,
|
private boolean matchesPreviousPasswords(String password, String username,
|
||||||
int historySize) {
|
int historySize) throws GuacamoleException {
|
||||||
|
|
||||||
// No need to compare if no history is relevant
|
// No need to compare if no history is relevant
|
||||||
if (historySize <= 0)
|
if (historySize <= 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Check password against all recorded hashes
|
// Check password against all recorded hashes
|
||||||
List<PasswordRecordModel> history = passwordRecordMapper.select(username, historySize);
|
List<PasswordRecordModel> history = passwordRecordMapper.select(username,
|
||||||
|
historySize, environment.getCaseSensitiveUsernames());
|
||||||
for (PasswordRecordModel record : history) {
|
for (PasswordRecordModel record : history) {
|
||||||
|
|
||||||
byte[] hash = encryptionService.createPasswordHash(password, record.getPasswordSalt());
|
byte[] hash = encryptionService.createPasswordHash(password, record.getPasswordSalt());
|
||||||
|
@@ -34,6 +34,7 @@ import java.util.Set;
|
|||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
import org.apache.guacamole.auth.jdbc.JDBCEnvironment;
|
||||||
import org.apache.guacamole.auth.jdbc.user.ModeledAuthenticatedUser;
|
import org.apache.guacamole.auth.jdbc.user.ModeledAuthenticatedUser;
|
||||||
import org.apache.guacamole.auth.jdbc.connection.ModeledConnection;
|
import org.apache.guacamole.auth.jdbc.connection.ModeledConnection;
|
||||||
import org.apache.guacamole.auth.jdbc.connectiongroup.ModeledConnectionGroup;
|
import org.apache.guacamole.auth.jdbc.connectiongroup.ModeledConnectionGroup;
|
||||||
@@ -168,6 +169,12 @@ public abstract class AbstractGuacamoleTunnelService implements GuacamoleTunnelS
|
|||||||
@Inject
|
@Inject
|
||||||
private SharedConnectionMap connectionMap;
|
private SharedConnectionMap connectionMap;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Guacamole server environment.
|
||||||
|
*/
|
||||||
|
@Inject
|
||||||
|
private JDBCEnvironment environment;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* All active connections through the tunnel having a given UUID.
|
* All active connections through the tunnel having a given UUID.
|
||||||
*/
|
*/
|
||||||
@@ -470,7 +477,9 @@ public abstract class AbstractGuacamoleTunnelService implements GuacamoleTunnelS
|
|||||||
// Record new active connection
|
// Record new active connection
|
||||||
Runnable cleanupTask = new ConnectionCleanupTask(activeConnection);
|
Runnable cleanupTask = new ConnectionCleanupTask(activeConnection);
|
||||||
try {
|
try {
|
||||||
connectionRecordMapper.insert(activeConnection.getModel()); // This MUST happen before getUUID() is invoked, to ensure the ID driving the UUID exists
|
// This MUST happen before getUUID() is invoked, to ensure the ID driving the UUID exists
|
||||||
|
connectionRecordMapper.insert(activeConnection.getModel(),
|
||||||
|
environment.getCaseSensitiveUsernames());
|
||||||
activeTunnels.put(activeConnection.getUUID().toString(), activeConnection);
|
activeTunnels.put(activeConnection.getUUID().toString(), activeConnection);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -195,4 +195,9 @@ public class ModeledAuthenticatedUser extends RemoteAuthenticatedUser {
|
|||||||
return getUser().isPrivileged();
|
return getUser().isPrivileged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isCaseSensitive() {
|
||||||
|
return user.isCaseSensitive();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -36,6 +36,7 @@ import java.util.TimeZone;
|
|||||||
import org.apache.guacamole.auth.jdbc.security.PasswordEncryptionService;
|
import org.apache.guacamole.auth.jdbc.security.PasswordEncryptionService;
|
||||||
import org.apache.guacamole.auth.jdbc.security.SaltService;
|
import org.apache.guacamole.auth.jdbc.security.SaltService;
|
||||||
import org.apache.guacamole.GuacamoleException;
|
import org.apache.guacamole.GuacamoleException;
|
||||||
|
import org.apache.guacamole.auth.jdbc.JDBCEnvironment;
|
||||||
import org.apache.guacamole.auth.jdbc.base.ModeledPermissions;
|
import org.apache.guacamole.auth.jdbc.base.ModeledPermissions;
|
||||||
import org.apache.guacamole.form.BooleanField;
|
import org.apache.guacamole.form.BooleanField;
|
||||||
import org.apache.guacamole.form.DateField;
|
import org.apache.guacamole.form.DateField;
|
||||||
@@ -181,6 +182,13 @@ public class ModeledUser extends ModeledPermissions<UserModel> implements User {
|
|||||||
@Inject
|
@Inject
|
||||||
private Provider<UserRecordSet> userRecordSetProvider;
|
private Provider<UserRecordSet> userRecordSetProvider;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The environment associated with this instance of the JDBC authentication
|
||||||
|
* module.
|
||||||
|
*/
|
||||||
|
@Inject
|
||||||
|
private JDBCEnvironment environment;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether attributes which control access restrictions should be exposed
|
* Whether attributes which control access restrictions should be exposed
|
||||||
* via getAttributes() or allowed to be set via setAttributes().
|
* via getAttributes() or allowed to be set via setAttributes().
|
||||||
@@ -781,4 +789,17 @@ public class ModeledUser extends ModeledPermissions<UserModel> implements User {
|
|||||||
return (getModel().getEntityID() == null);
|
return (getModel().getEntityID() == null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isCaseSensitive() {
|
||||||
|
try {
|
||||||
|
return environment.getCaseSensitiveUsernames();
|
||||||
|
}
|
||||||
|
catch (GuacamoleException e) {
|
||||||
|
logger.error("Failed to retrieve the configuration for case-sensitive usernames: {}."
|
||||||
|
+ " Usernames comparisons will be case-sensitive.", e.getMessage());
|
||||||
|
logger.debug("Exception caught when attempting to read the configuration.", e);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -176,8 +176,12 @@ public class ModeledUserContext extends RestrictedObject
|
|||||||
* invocation has any effect. If this function is never invoked, no
|
* invocation has any effect. If this function is never invoked, no
|
||||||
* activity record will be recorded, including when this UserContext is
|
* activity record will be recorded, including when this UserContext is
|
||||||
* invalidated.
|
* invalidated.
|
||||||
|
*
|
||||||
|
* @throws GuacamoleException
|
||||||
|
* If an error occurs retrieving configuration information from the
|
||||||
|
* environment.
|
||||||
*/
|
*/
|
||||||
public void recordUserLogin() {
|
public void recordUserLogin() throws GuacamoleException {
|
||||||
|
|
||||||
// Do nothing if invoked multiple times
|
// Do nothing if invoked multiple times
|
||||||
if (userRecord != null)
|
if (userRecord != null)
|
||||||
@@ -190,7 +194,7 @@ public class ModeledUserContext extends RestrictedObject
|
|||||||
userRecord.setRemoteHost(getCurrentUser().getCredentials().getRemoteAddress());
|
userRecord.setRemoteHost(getCurrentUser().getCredentials().getRemoteAddress());
|
||||||
|
|
||||||
// Insert record representing login
|
// Insert record representing login
|
||||||
userRecordMapper.insert(userRecord);
|
userRecordMapper.insert(userRecord, environment.getCaseSensitiveUsernames());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -39,13 +39,18 @@ public interface PasswordRecordMapper extends ModeledDirectoryObjectMapper<UserM
|
|||||||
* @param maxHistorySize
|
* @param maxHistorySize
|
||||||
* The maximum number of records to maintain for each user.
|
* The maximum number of records to maintain for each user.
|
||||||
*
|
*
|
||||||
|
* @param caseSensitive
|
||||||
|
* true if the username being queried should be evaluated in a
|
||||||
|
* case-sensitive manner, otherwise false.
|
||||||
|
*
|
||||||
* @return
|
* @return
|
||||||
* A collection of all password records associated with the user having
|
* A collection of all password records associated with the user having
|
||||||
* the given username. This collection will be empty if no such user
|
* the given username. This collection will be empty if no such user
|
||||||
* exists.
|
* exists.
|
||||||
*/
|
*/
|
||||||
List<PasswordRecordModel> select(@Param("username") String username,
|
List<PasswordRecordModel> select(@Param("username") String username,
|
||||||
@Param("maxHistorySize") int maxHistorySize);
|
@Param("maxHistorySize") int maxHistorySize,
|
||||||
|
@Param("caseSensitive") boolean caseSensitive);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inserts the given password record. Old records exceeding the maximum
|
* Inserts the given password record. Old records exceeding the maximum
|
||||||
|
@@ -19,6 +19,7 @@
|
|||||||
|
|
||||||
package org.apache.guacamole.auth.jdbc.user;
|
package org.apache.guacamole.auth.jdbc.user;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
import org.apache.guacamole.auth.jdbc.base.ModeledDirectoryObjectMapper;
|
import org.apache.guacamole.auth.jdbc.base.ModeledDirectoryObjectMapper;
|
||||||
import org.apache.ibatis.annotations.Param;
|
import org.apache.ibatis.annotations.Param;
|
||||||
|
|
||||||
@@ -34,9 +35,81 @@ public interface UserMapper extends ModeledDirectoryObjectMapper<UserModel> {
|
|||||||
* @param username
|
* @param username
|
||||||
* The username of the user to return.
|
* The username of the user to return.
|
||||||
*
|
*
|
||||||
|
* @param caseSensitive
|
||||||
|
* true if the search should evaluate usernames in a case-sensitive
|
||||||
|
* manner, otherwise false.
|
||||||
|
*
|
||||||
* @return
|
* @return
|
||||||
* The user having the given username, or null if no such user exists.
|
* The user having the given username, or null if no such user exists.
|
||||||
*/
|
*/
|
||||||
UserModel selectOne(@Param("username") String username);
|
UserModel selectOne(@Param("username") String username,
|
||||||
|
@Param("caseSensitive") boolean caseSensitive);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Selects all users which have the given identifiers. If an identifier
|
||||||
|
* has no corresponding object, it will be ignored. This should only be
|
||||||
|
* called on behalf of a system administrator. If users are needed by a
|
||||||
|
* non-administrative user who must have explicit read rights, use
|
||||||
|
* selectReadable() instead.
|
||||||
|
*
|
||||||
|
* @param identifiers
|
||||||
|
* The identifiers of the users to return.
|
||||||
|
*
|
||||||
|
* @param caseSensitive
|
||||||
|
* true if the query should evaluate username identifiers in a
|
||||||
|
* case-sensitive manner, otherwise false.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* A Collection of all objects having the given identifiers.
|
||||||
|
*/
|
||||||
|
Collection<UserModel> select(@Param("identifiers") Collection<String> identifiers,
|
||||||
|
@Param("caseSensitive") boolean caseSensitive);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Selects all users which have the given identifiers and are explicitly
|
||||||
|
* readable by the given user. If an identifier has no corresponding
|
||||||
|
* object, or the corresponding user is unreadable, it will be ignored.
|
||||||
|
* If users are needed by a system administrator (who, by definition,
|
||||||
|
* does not need explicit read rights), use select() instead.
|
||||||
|
*
|
||||||
|
* @param user
|
||||||
|
* The user whose permissions should determine whether an object
|
||||||
|
* is returned.
|
||||||
|
*
|
||||||
|
* @param identifiers
|
||||||
|
* The identifiers of the users to return.
|
||||||
|
*
|
||||||
|
* @param effectiveGroups
|
||||||
|
* The identifiers of any known effective groups that should be taken
|
||||||
|
* into account, such as those defined externally to the database.
|
||||||
|
*
|
||||||
|
* @param caseSensitive
|
||||||
|
* true if the query should evaluate username identifiers in a
|
||||||
|
* case-sensitive manner, otherwise false.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* A Collection of all objects having the given identifiers.
|
||||||
|
*/
|
||||||
|
Collection<UserModel> selectReadable(@Param("user") UserModel user,
|
||||||
|
@Param("identifiers") Collection<String> identifiers,
|
||||||
|
@Param("effectiveGroups") Collection<String> effectiveGroups,
|
||||||
|
@Param("caseSensitive") boolean caseSensitive);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deletes the given user from the database. If the user does not
|
||||||
|
* exist, this operation has no effect.
|
||||||
|
*
|
||||||
|
* @param identifier
|
||||||
|
* The identifier of the user to delete.
|
||||||
|
*
|
||||||
|
* @param caseSensitive
|
||||||
|
* true if the query should evaluate username identifiers in a
|
||||||
|
* case-sensitive manner, otherwise false.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* The number of rows deleted.
|
||||||
|
*/
|
||||||
|
int delete(@Param("identifier") String identifier,
|
||||||
|
@Param("caseSensitive") boolean caseSensitive);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -33,6 +33,7 @@ import org.apache.guacamole.auth.jdbc.base.ModeledDirectoryObjectService;
|
|||||||
import org.apache.guacamole.GuacamoleClientException;
|
import org.apache.guacamole.GuacamoleClientException;
|
||||||
import org.apache.guacamole.GuacamoleException;
|
import org.apache.guacamole.GuacamoleException;
|
||||||
import org.apache.guacamole.GuacamoleUnsupportedException;
|
import org.apache.guacamole.GuacamoleUnsupportedException;
|
||||||
|
import org.apache.guacamole.auth.jdbc.JDBCEnvironment;
|
||||||
import org.apache.guacamole.auth.jdbc.base.ActivityRecordModel;
|
import org.apache.guacamole.auth.jdbc.base.ActivityRecordModel;
|
||||||
import org.apache.guacamole.auth.jdbc.base.ActivityRecordSearchTerm;
|
import org.apache.guacamole.auth.jdbc.base.ActivityRecordSearchTerm;
|
||||||
import org.apache.guacamole.auth.jdbc.base.ActivityRecordSortPredicate;
|
import org.apache.guacamole.auth.jdbc.base.ActivityRecordSortPredicate;
|
||||||
@@ -156,6 +157,12 @@ public class UserService extends ModeledDirectoryObjectService<ModeledUser, User
|
|||||||
@Inject
|
@Inject
|
||||||
private PasswordPolicyService passwordPolicyService;
|
private PasswordPolicyService passwordPolicyService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The server environment for retrieving configuration.
|
||||||
|
*/
|
||||||
|
@Inject
|
||||||
|
private JDBCEnvironment environment;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected ModeledDirectoryObjectMapper<UserModel> getObjectMapper() {
|
protected ModeledDirectoryObjectMapper<UserModel> getObjectMapper() {
|
||||||
return userMapper;
|
return userMapper;
|
||||||
@@ -241,7 +248,8 @@ public class UserService extends ModeledDirectoryObjectService<ModeledUser, User
|
|||||||
throw new GuacamoleClientException("The username must not be blank.");
|
throw new GuacamoleClientException("The username must not be blank.");
|
||||||
|
|
||||||
// Do not create duplicate users
|
// Do not create duplicate users
|
||||||
Collection<UserModel> existing = userMapper.select(Collections.singleton(model.getIdentifier()));
|
Collection<UserModel> existing = userMapper.select(Collections.singleton(
|
||||||
|
model.getIdentifier()), environment.getCaseSensitiveUsernames());
|
||||||
if (!existing.isEmpty())
|
if (!existing.isEmpty())
|
||||||
throw new GuacamoleClientException("User \"" + model.getIdentifier() + "\" already exists.");
|
throw new GuacamoleClientException("User \"" + model.getIdentifier() + "\" already exists.");
|
||||||
|
|
||||||
@@ -277,7 +285,8 @@ public class UserService extends ModeledDirectoryObjectService<ModeledUser, User
|
|||||||
throw new GuacamoleClientException("The username must not be blank.");
|
throw new GuacamoleClientException("The username must not be blank.");
|
||||||
|
|
||||||
// Check whether such a user is already present
|
// Check whether such a user is already present
|
||||||
UserModel existing = userMapper.selectOne(model.getIdentifier());
|
UserModel existing = userMapper.selectOne(model.getIdentifier(),
|
||||||
|
environment.getCaseSensitiveUsernames());
|
||||||
if (existing != null) {
|
if (existing != null) {
|
||||||
|
|
||||||
// Do not rename to existing user
|
// Do not rename to existing user
|
||||||
@@ -338,6 +347,17 @@ public class UserService extends ModeledDirectoryObjectService<ModeledUser, User
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void deleteObject(ModeledAuthenticatedUser user, String identifier)
|
||||||
|
throws GuacamoleException {
|
||||||
|
|
||||||
|
beforeDelete(user, identifier);
|
||||||
|
|
||||||
|
// Delete object
|
||||||
|
userMapper.delete(identifier, environment.getCaseSensitiveUsernames());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean isValidIdentifier(String identifier) {
|
protected boolean isValidIdentifier(String identifier) {
|
||||||
|
|
||||||
@@ -375,7 +395,8 @@ public class UserService extends ModeledDirectoryObjectService<ModeledUser, User
|
|||||||
String password = credentials.getPassword();
|
String password = credentials.getPassword();
|
||||||
|
|
||||||
// Retrieve corresponding user model, if such a user exists
|
// Retrieve corresponding user model, if such a user exists
|
||||||
UserModel userModel = userMapper.selectOne(username);
|
UserModel userModel = userMapper.selectOne(username,
|
||||||
|
environment.getCaseSensitiveUsernames());
|
||||||
if (userModel == null)
|
if (userModel == null)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
@@ -416,7 +437,8 @@ public class UserService extends ModeledDirectoryObjectService<ModeledUser, User
|
|||||||
AuthenticatedUser authenticatedUser) throws GuacamoleException {
|
AuthenticatedUser authenticatedUser) throws GuacamoleException {
|
||||||
|
|
||||||
// Retrieve corresponding user model, if such a user exists
|
// Retrieve corresponding user model, if such a user exists
|
||||||
UserModel userModel = userMapper.selectOne(authenticatedUser.getIdentifier());
|
UserModel userModel = userMapper.selectOne(authenticatedUser.getIdentifier(),
|
||||||
|
environment.getCaseSensitiveUsernames());
|
||||||
if (userModel == null)
|
if (userModel == null)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
@@ -614,14 +636,16 @@ public class UserService extends ModeledDirectoryObjectService<ModeledUser, User
|
|||||||
// Bypass permission checks if the user is privileged or has System-level audit permissions
|
// Bypass permission checks if the user is privileged or has System-level audit permissions
|
||||||
if (user.isPrivileged() || user.getUser().getEffectivePermissions().getSystemPermissions().hasPermission(SystemPermission.Type.AUDIT))
|
if (user.isPrivileged() || user.getUser().getEffectivePermissions().getSystemPermissions().hasPermission(SystemPermission.Type.AUDIT))
|
||||||
searchResults = userRecordMapper.search(username, recordIdentifier,
|
searchResults = userRecordMapper.search(username, recordIdentifier,
|
||||||
requiredContents, sortPredicates, limit);
|
requiredContents, sortPredicates, limit,
|
||||||
|
environment.getCaseSensitiveUsernames());
|
||||||
|
|
||||||
// Otherwise only return explicitly readable history records
|
// Otherwise only return explicitly readable history records
|
||||||
else
|
else
|
||||||
searchResults = userRecordMapper.searchReadable(username,
|
searchResults = userRecordMapper.searchReadable(username,
|
||||||
user.getUser().getModel(), recordIdentifier,
|
user.getUser().getModel(), recordIdentifier,
|
||||||
requiredContents, sortPredicates, limit,
|
requiredContents, sortPredicates, limit,
|
||||||
user.getEffectiveUserGroups());
|
user.getEffectiveUserGroups(),
|
||||||
|
environment.getCaseSensitiveUsernames());
|
||||||
|
|
||||||
return getObjectInstances(searchResults);
|
return getObjectInstances(searchResults);
|
||||||
|
|
||||||
|
@@ -19,10 +19,67 @@
|
|||||||
|
|
||||||
package org.apache.guacamole.auth.jdbc.usergroup;
|
package org.apache.guacamole.auth.jdbc.usergroup;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
import org.apache.guacamole.auth.jdbc.base.ObjectRelationMapper;
|
import org.apache.guacamole.auth.jdbc.base.ObjectRelationMapper;
|
||||||
|
import org.apache.ibatis.annotations.Param;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Mapper for the one-to-many relationship between a user group and its user
|
* Mapper for the one-to-many relationship between a user group and its user
|
||||||
* members.
|
* members.
|
||||||
*/
|
*/
|
||||||
public interface UserGroupMemberUserMapper extends ObjectRelationMapper<UserGroupModel> {}
|
public interface UserGroupMemberUserMapper extends ObjectRelationMapper<UserGroupModel> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Inserts rows as necessary to establish the one-to-many relationship
|
||||||
|
* represented by the RelatedObjectSet between the given parent and
|
||||||
|
* children. If the relation for any parent/child pair is already present,
|
||||||
|
* no attempt is made to insert a new row for that relation.
|
||||||
|
*
|
||||||
|
* @param parent
|
||||||
|
* The model of the object on the parent side of the one-to-many
|
||||||
|
* relationship represented by the RelatedObjectSet.
|
||||||
|
*
|
||||||
|
* @param children
|
||||||
|
* The identifiers of the objects on the child side of the one-to-many
|
||||||
|
* relationship represented by the RelatedObjectSet.
|
||||||
|
*
|
||||||
|
* @param caseSensitive
|
||||||
|
* True if username case should be respected when looking up the username
|
||||||
|
* in the guacamole_entity table, or false if the query to the
|
||||||
|
* guacamole_entity table should be done case-insensitively.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* The number of rows inserted.
|
||||||
|
*/
|
||||||
|
int insert(@Param("parent") UserGroupModel parent,
|
||||||
|
@Param("children") Collection<String> children,
|
||||||
|
@Param("caseSensitive") boolean caseSensitive);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deletes rows as necessary to modify the one-to-many relationship
|
||||||
|
* represented by the RelatedObjectSet between the given parent and
|
||||||
|
* children. If the relation for any parent/child pair does not exist,
|
||||||
|
* that specific relation is ignored, and deletion proceeds with the
|
||||||
|
* remaining relations.
|
||||||
|
*
|
||||||
|
* @param parent
|
||||||
|
* The model of the object on the parent side of the one-to-many
|
||||||
|
* relationship represented by the RelatedObjectSet.
|
||||||
|
*
|
||||||
|
* @param children
|
||||||
|
* The identifiers of the objects on the child side of the one-to-many
|
||||||
|
* relationship represented by the RelatedObjectSet.
|
||||||
|
*
|
||||||
|
* @param caseSensitive
|
||||||
|
* True if username case should be respected when looking up the username
|
||||||
|
* in the guacamole_entity table, or false if the query to the
|
||||||
|
* guacamole_entity table should be done case-insensitively.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* The number of rows deleted.
|
||||||
|
*/
|
||||||
|
int delete(@Param("parent") UserGroupModel parent,
|
||||||
|
@Param("children") Collection<String> children,
|
||||||
|
@Param("caseSesitive") boolean caseSensitive);
|
||||||
|
|
||||||
|
}
|
||||||
|
@@ -439,7 +439,30 @@ public class MySQLEnvironment extends JDBCEnvironment {
|
|||||||
// Enforce access window restrictions for active sessions unless explicitly disabled
|
// Enforce access window restrictions for active sessions unless explicitly disabled
|
||||||
return getProperty(
|
return getProperty(
|
||||||
MySQLGuacamoleProperties.MYSQL_ENFORCE_ACCESS_WINDOWS_FOR_ACTIVE_SESSIONS,
|
MySQLGuacamoleProperties.MYSQL_ENFORCE_ACCESS_WINDOWS_FOR_ACTIVE_SESSIONS,
|
||||||
true);
|
true
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean getCaseSensitiveUsernames() throws GuacamoleException {
|
||||||
|
|
||||||
|
// Get the configured value for the property.
|
||||||
|
boolean caseSensitiveUsernames = getProperty(
|
||||||
|
MySQLGuacamoleProperties.MYSQL_CASE_SENSITIVE_USERNAMES,
|
||||||
|
super.getCaseSensitiveUsernames()
|
||||||
|
);
|
||||||
|
|
||||||
|
// If property has been set to true, warn the admin.
|
||||||
|
if (caseSensitiveUsernames)
|
||||||
|
logger.warn("You have enabled case-sensitive usernames; however, "
|
||||||
|
+ "MySQL's default collations do not support case-sensitive "
|
||||||
|
+ "string comparisons. If you really want case-sensitive "
|
||||||
|
+ "usernames you will need to configure your database "
|
||||||
|
+ "appropriately.");
|
||||||
|
|
||||||
|
// Return the configured setting.
|
||||||
|
return caseSensitiveUsernames;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -303,4 +303,18 @@ public class MySQLGuacamoleProperties {
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A property used to configure whether or not usernames within the MySQL
|
||||||
|
* JDBC module should be treated as case-sensitive. Be aware that MySQL's
|
||||||
|
* default database collations do not do case-sensitive comparisons, so in
|
||||||
|
* many cases they will effectively be case-insensitive.
|
||||||
|
*/
|
||||||
|
public static final BooleanGuacamoleProperty MYSQL_CASE_SENSITIVE_USERNAMES =
|
||||||
|
new BooleanGuacamoleProperty() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() { return "mysql-case-sensitive-usernames"; }
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -61,7 +61,14 @@
|
|||||||
(SELECT user_id FROM guacamole_user
|
(SELECT user_id FROM guacamole_user
|
||||||
JOIN guacamole_entity ON guacamole_user.entity_id = guacamole_entity.entity_id
|
JOIN guacamole_entity ON guacamole_user.entity_id = guacamole_entity.entity_id
|
||||||
WHERE
|
WHERE
|
||||||
guacamole_entity.name = #{record.username,jdbcType=VARCHAR}
|
<choose>
|
||||||
|
<when test="caseSensitive">
|
||||||
|
guacamole_entity.name = #{record.username,jdbcType=VARCHAR}
|
||||||
|
</when>
|
||||||
|
<otherwise>
|
||||||
|
LOWER(guacamole_entity.name) = LOWER(#{record.username,jdbcType=VARCHAR})
|
||||||
|
</otherwise>
|
||||||
|
</choose>
|
||||||
AND guacamole_entity.type = 'USER'),
|
AND guacamole_entity.type = 'USER'),
|
||||||
#{record.username,jdbcType=VARCHAR},
|
#{record.username,jdbcType=VARCHAR},
|
||||||
#{record.startDate,jdbcType=TIMESTAMP},
|
#{record.startDate,jdbcType=TIMESTAMP},
|
||||||
@@ -112,7 +119,15 @@
|
|||||||
guacamole_connection_history.user_id IN (
|
guacamole_connection_history.user_id IN (
|
||||||
SELECT user_id
|
SELECT user_id
|
||||||
FROM guacamole_user
|
FROM guacamole_user
|
||||||
WHERE POSITION(#{term.term,jdbcType=VARCHAR} IN username) > 0
|
WHERE
|
||||||
|
<choose>
|
||||||
|
<when test="caseSensitive">
|
||||||
|
POSITION(#{term.term,jdbcType=VARCHAR} IN username) > 0
|
||||||
|
</when>
|
||||||
|
<otherwise>
|
||||||
|
POSITION(LOWER(#{term.term,jdbcType=VARCHAR}) IN LOWER(username)) > 0
|
||||||
|
</otherwise>
|
||||||
|
</choose>
|
||||||
)
|
)
|
||||||
|
|
||||||
OR guacamole_connection_history.connection_id IN (
|
OR guacamole_connection_history.connection_id IN (
|
||||||
@@ -200,7 +215,14 @@
|
|||||||
FROM guacamole_user
|
FROM guacamole_user
|
||||||
JOIN guacamole_entity ON guacamole_user.entity_id = guacamole_entity.entity_id
|
JOIN guacamole_entity ON guacamole_user.entity_id = guacamole_entity.entity_id
|
||||||
WHERE
|
WHERE
|
||||||
POSITION(#{term.term,jdbcType=VARCHAR} IN guacamole_entity.name) > 0
|
<choose>
|
||||||
|
<when test="caseSensitive">
|
||||||
|
POSITION(#{term.term,jdbcType=VARCHAR} IN guacamole_entity.name) > 0
|
||||||
|
</when>
|
||||||
|
<otherwise>
|
||||||
|
POSITION(LOWER(#{term.term,jdbcType=VARCHAR}) IN LOWER(guacamole_entity.name)) > 0
|
||||||
|
</otherwise>
|
||||||
|
</choose>
|
||||||
AND guacamole_entity.type = 'USER'
|
AND guacamole_entity.type = 'USER'
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@@ -68,7 +68,15 @@
|
|||||||
<property name="groups" value="effectiveGroups"/>
|
<property name="groups" value="effectiveGroups"/>
|
||||||
</include>
|
</include>
|
||||||
AND permission = #{type,jdbcType=VARCHAR}
|
AND permission = #{type,jdbcType=VARCHAR}
|
||||||
AND affected_entity.name = #{identifier,jdbcType=VARCHAR}
|
AND
|
||||||
|
<choose>
|
||||||
|
<when test="caseSensitive">
|
||||||
|
affected_entity.name = #{identifier,jdbcType=VARCHAR}
|
||||||
|
</when>
|
||||||
|
<otherwise>
|
||||||
|
LOWER(affected_entity.name) = LOWER(#{identifier,jdbcType=VARCHAR})
|
||||||
|
</otherwise>
|
||||||
|
</choose>
|
||||||
AND affected_entity.type = 'USER'
|
AND affected_entity.type = 'USER'
|
||||||
|
|
||||||
</select>
|
</select>
|
||||||
@@ -86,11 +94,23 @@
|
|||||||
<property name="entityID" value="#{entity.entityID,jdbcType=INTEGER}"/>
|
<property name="entityID" value="#{entity.entityID,jdbcType=INTEGER}"/>
|
||||||
<property name="groups" value="effectiveGroups"/>
|
<property name="groups" value="effectiveGroups"/>
|
||||||
</include>
|
</include>
|
||||||
AND affected_entity.name IN
|
AND
|
||||||
<foreach collection="identifiers" item="identifier"
|
<choose>
|
||||||
|
<when test="caseSensitive">
|
||||||
|
affected_entity.name IN
|
||||||
|
<foreach collection="identifiers" item="identifier"
|
||||||
open="(" separator="," close=")">
|
open="(" separator="," close=")">
|
||||||
#{identifier,jdbcType=VARCHAR}
|
#{identifier,jdbcType=VARCHAR}
|
||||||
</foreach>
|
</foreach>
|
||||||
|
</when>
|
||||||
|
<otherwise>
|
||||||
|
LOWER(affected_entity.name) IN
|
||||||
|
<foreach collection="identifiers" item="identifier"
|
||||||
|
open="(" separator="," close=")">
|
||||||
|
LOWER(#{identifier,jdbcType=VARCHAR})
|
||||||
|
</foreach>
|
||||||
|
</otherwise>
|
||||||
|
</choose>
|
||||||
AND permission IN
|
AND permission IN
|
||||||
<foreach collection="permissions" item="permission"
|
<foreach collection="permissions" item="permission"
|
||||||
open="(" separator="," close=")">
|
open="(" separator="," close=")">
|
||||||
@@ -108,13 +128,26 @@
|
|||||||
JOIN guacamole_user affected_user ON guacamole_user_permission.affected_user_id = affected_user.user_id
|
JOIN guacamole_user affected_user ON guacamole_user_permission.affected_user_id = affected_user.user_id
|
||||||
JOIN guacamole_entity affected_entity ON affected_user.entity_id = affected_entity.entity_id
|
JOIN guacamole_entity affected_entity ON affected_user.entity_id = affected_entity.entity_id
|
||||||
WHERE
|
WHERE
|
||||||
(guacamole_user_permission.entity_id, permission, affected_entity.name) IN
|
<choose>
|
||||||
<foreach collection="permissions" item="permission"
|
<when test="caseSensitive">
|
||||||
open="(" separator="," close=")">
|
(guacamole_user_permission.entity_id, permission, affected_entity.name) IN
|
||||||
(#{permission.entityID,jdbcType=INTEGER},
|
<foreach collection="permissions" item="permission"
|
||||||
#{permission.type,jdbcType=VARCHAR},
|
open="(" separator="," close=")">
|
||||||
#{permission.objectIdentifier,jdbcType=VARCHAR})
|
(#{permission.entityID,jdbcType=INTEGER},
|
||||||
</foreach>
|
#{permission.type,jdbcType=VARCHAR},
|
||||||
|
#{permission.objectIdentifier,jdbcType=VARCHAR})
|
||||||
|
</foreach>
|
||||||
|
</when>
|
||||||
|
<otherwise>
|
||||||
|
AND (guacamole_user_permission.entity_id, permission, LOWER(affected_entity.name)) IN
|
||||||
|
<foreach collection="permissions" item="permission"
|
||||||
|
open="(" separator="," close=")">
|
||||||
|
(#{permission.entityID,jdbcType=INTEGER},
|
||||||
|
#{permission.type,jdbcType=VARCHAR},
|
||||||
|
LOWER(#{permission.objectIdentifier,jdbcType=VARCHAR}))
|
||||||
|
</foreach>
|
||||||
|
</otherwise>
|
||||||
|
</choose>
|
||||||
AND affected_entity.type = 'USER'
|
AND affected_entity.type = 'USER'
|
||||||
|
|
||||||
</delete>
|
</delete>
|
||||||
@@ -140,7 +173,14 @@
|
|||||||
</foreach>
|
</foreach>
|
||||||
AS permissions
|
AS permissions
|
||||||
JOIN guacamole_entity affected_entity ON
|
JOIN guacamole_entity affected_entity ON
|
||||||
affected_entity.name = permissions.affected_name
|
<choose>
|
||||||
|
<when test="caseSensitive">
|
||||||
|
affected_entity.name = permissions.affected_name
|
||||||
|
</when>
|
||||||
|
<otherwise>
|
||||||
|
LOWER(affected_entity.name) = LOWER(permissions.affected_name)
|
||||||
|
</otherwise>
|
||||||
|
</choose>
|
||||||
AND affected_entity.type = 'USER'
|
AND affected_entity.type = 'USER'
|
||||||
JOIN guacamole_user affected_user ON affected_user.entity_id = affected_entity.entity_id
|
JOIN guacamole_user affected_user ON affected_user.entity_id = affected_entity.entity_id
|
||||||
|
|
||||||
|
@@ -43,7 +43,14 @@
|
|||||||
JOIN guacamole_user ON guacamole_user_password_history.user_id = guacamole_user.user_id
|
JOIN guacamole_user ON guacamole_user_password_history.user_id = guacamole_user.user_id
|
||||||
JOIN guacamole_entity ON guacamole_user.entity_id = guacamole_entity.entity_id
|
JOIN guacamole_entity ON guacamole_user.entity_id = guacamole_entity.entity_id
|
||||||
WHERE
|
WHERE
|
||||||
guacamole_entity.name = #{username,jdbcType=VARCHAR}
|
<choose>
|
||||||
|
<when test="caseSensitive">
|
||||||
|
guacamole_entity.name = #{username,jdbcType=VARCHAR}
|
||||||
|
</when>
|
||||||
|
<otherwise>
|
||||||
|
LOWER(guacamole_entity.name) = LOWER(#{username,jdbcType=VARCHAR})
|
||||||
|
</otherwise>
|
||||||
|
</choose>
|
||||||
ORDER BY
|
ORDER BY
|
||||||
guacamole_user_password_history.password_date DESC
|
guacamole_user_password_history.password_date DESC
|
||||||
LIMIT #{maxHistorySize}
|
LIMIT #{maxHistorySize}
|
||||||
|
@@ -130,10 +130,26 @@
|
|||||||
FROM guacamole_user
|
FROM guacamole_user
|
||||||
JOIN guacamole_entity ON guacamole_user.entity_id = guacamole_entity.entity_id
|
JOIN guacamole_entity ON guacamole_user.entity_id = guacamole_entity.entity_id
|
||||||
LEFT JOIN guacamole_user_history ON guacamole_user_history.user_id = guacamole_user.user_id
|
LEFT JOIN guacamole_user_history ON guacamole_user_history.user_id = guacamole_user.user_id
|
||||||
WHERE guacamole_entity.name IN
|
WHERE
|
||||||
|
<choose>
|
||||||
|
<when test="caseSensitive">
|
||||||
|
guacamole_entity.name
|
||||||
|
</when>
|
||||||
|
<otherwise>
|
||||||
|
LOWER(guacamole_entity.name)
|
||||||
|
</otherwise>
|
||||||
|
</choose>
|
||||||
|
IN
|
||||||
<foreach collection="identifiers" item="identifier"
|
<foreach collection="identifiers" item="identifier"
|
||||||
open="(" separator="," close=")">
|
open="(" separator="," close=")">
|
||||||
#{identifier,jdbcType=VARCHAR}
|
<choose>
|
||||||
|
<when test="caseSensitive">
|
||||||
|
#{identifier,jdbcType=VARCHAR}
|
||||||
|
</when>
|
||||||
|
<otherwise>
|
||||||
|
LOWER(#{identifier,jdbcType=VARCHAR})
|
||||||
|
</otherwise>
|
||||||
|
</choose>
|
||||||
</foreach>
|
</foreach>
|
||||||
AND guacamole_entity.type = 'USER'
|
AND guacamole_entity.type = 'USER'
|
||||||
GROUP BY guacamole_user.user_id, guacamole_entity.entity_id;
|
GROUP BY guacamole_user.user_id, guacamole_entity.entity_id;
|
||||||
@@ -145,10 +161,26 @@
|
|||||||
FROM guacamole_user_attribute
|
FROM guacamole_user_attribute
|
||||||
JOIN guacamole_user ON guacamole_user.user_id = guacamole_user_attribute.user_id
|
JOIN guacamole_user ON guacamole_user.user_id = guacamole_user_attribute.user_id
|
||||||
JOIN guacamole_entity ON guacamole_user.entity_id = guacamole_entity.entity_id
|
JOIN guacamole_entity ON guacamole_user.entity_id = guacamole_entity.entity_id
|
||||||
WHERE guacamole_entity.name IN
|
WHERE
|
||||||
|
<choose>
|
||||||
|
<when test="caseSensitive">
|
||||||
|
guacamole_entity.name
|
||||||
|
</when>
|
||||||
|
<otherwise>
|
||||||
|
LOWER(guacamole_entity.name)
|
||||||
|
</otherwise>
|
||||||
|
</choose>
|
||||||
|
IN
|
||||||
<foreach collection="identifiers" item="identifier"
|
<foreach collection="identifiers" item="identifier"
|
||||||
open="(" separator="," close=")">
|
open="(" separator="," close=")">
|
||||||
#{identifier,jdbcType=VARCHAR}
|
<choose>
|
||||||
|
<when test="caseSensitive">
|
||||||
|
#{identifier,jdbcType=VARCHAR}
|
||||||
|
</when>
|
||||||
|
<otherwise>
|
||||||
|
LOWER(#{identifier,jdbcType=VARCHAR})
|
||||||
|
</otherwise>
|
||||||
|
</choose>
|
||||||
</foreach>
|
</foreach>
|
||||||
AND guacamole_entity.type = 'USER';
|
AND guacamole_entity.type = 'USER';
|
||||||
|
|
||||||
@@ -180,10 +212,26 @@
|
|||||||
FROM guacamole_user
|
FROM guacamole_user
|
||||||
JOIN guacamole_entity ON guacamole_user.entity_id = guacamole_entity.entity_id
|
JOIN guacamole_entity ON guacamole_user.entity_id = guacamole_entity.entity_id
|
||||||
LEFT JOIN guacamole_user_history ON guacamole_user_history.user_id = guacamole_user.user_id
|
LEFT JOIN guacamole_user_history ON guacamole_user_history.user_id = guacamole_user.user_id
|
||||||
WHERE guacamole_entity.name IN
|
WHERE
|
||||||
|
<choose>
|
||||||
|
<when test="caseSensitive">
|
||||||
|
guacamole_entity.name
|
||||||
|
</when>
|
||||||
|
<otherwise>
|
||||||
|
LOWER(guacamole_entity.name)
|
||||||
|
</otherwise>
|
||||||
|
</choose>
|
||||||
|
IN
|
||||||
<foreach collection="identifiers" item="identifier"
|
<foreach collection="identifiers" item="identifier"
|
||||||
open="(" separator="," close=")">
|
open="(" separator="," close=")">
|
||||||
#{identifier,jdbcType=VARCHAR}
|
<choose>
|
||||||
|
<when test="caseSensitive">
|
||||||
|
#{identifier,jdbcType=VARCHAR}
|
||||||
|
</when>
|
||||||
|
<otherwise>
|
||||||
|
LOWER(#{identifier,jdbcType=VARCHAR})
|
||||||
|
</otherwise>
|
||||||
|
</choose>
|
||||||
</foreach>
|
</foreach>
|
||||||
AND guacamole_entity.type = 'USER'
|
AND guacamole_entity.type = 'USER'
|
||||||
AND guacamole_user.user_id IN (
|
AND guacamole_user.user_id IN (
|
||||||
@@ -201,10 +249,26 @@
|
|||||||
FROM guacamole_user_attribute
|
FROM guacamole_user_attribute
|
||||||
JOIN guacamole_user ON guacamole_user.user_id = guacamole_user_attribute.user_id
|
JOIN guacamole_user ON guacamole_user.user_id = guacamole_user_attribute.user_id
|
||||||
JOIN guacamole_entity ON guacamole_user.entity_id = guacamole_entity.entity_id
|
JOIN guacamole_entity ON guacamole_user.entity_id = guacamole_entity.entity_id
|
||||||
WHERE guacamole_entity.name IN
|
WHERE
|
||||||
|
<choose>
|
||||||
|
<when test="caseSensitive">
|
||||||
|
guacamole_entity.name
|
||||||
|
</when>
|
||||||
|
<otherwise>
|
||||||
|
LOWER(guacamole_entity.name)
|
||||||
|
</otherwise>
|
||||||
|
</choose>
|
||||||
|
IN
|
||||||
<foreach collection="identifiers" item="identifier"
|
<foreach collection="identifiers" item="identifier"
|
||||||
open="(" separator="," close=")">
|
open="(" separator="," close=")">
|
||||||
#{identifier,jdbcType=VARCHAR}
|
<choose>
|
||||||
|
<when test="caseSensitive">
|
||||||
|
#{identifier,jdbcType=VARCHAR}
|
||||||
|
</when>
|
||||||
|
<otherwise>
|
||||||
|
LOWER(#{identifier,jdbcType=VARCHAR})
|
||||||
|
</otherwise>
|
||||||
|
</choose>
|
||||||
</foreach>
|
</foreach>
|
||||||
AND guacamole_entity.type = 'USER'
|
AND guacamole_entity.type = 'USER'
|
||||||
AND guacamole_user.user_id IN (
|
AND guacamole_user.user_id IN (
|
||||||
@@ -243,7 +307,14 @@
|
|||||||
JOIN guacamole_entity ON guacamole_user.entity_id = guacamole_entity.entity_id
|
JOIN guacamole_entity ON guacamole_user.entity_id = guacamole_entity.entity_id
|
||||||
LEFT JOIN guacamole_user_history ON guacamole_user_history.user_id = guacamole_user.user_id
|
LEFT JOIN guacamole_user_history ON guacamole_user_history.user_id = guacamole_user.user_id
|
||||||
WHERE
|
WHERE
|
||||||
guacamole_entity.name = #{username,jdbcType=VARCHAR}
|
<choose>
|
||||||
|
<when test="caseSensitive">
|
||||||
|
guacamole_entity.name = #{username,jdbcType=VARCHAR}
|
||||||
|
</when>
|
||||||
|
<otherwise>
|
||||||
|
LOWER(guacamole_entity.name) = LOWER(#{username,jdbcType=VARCHAR})
|
||||||
|
</otherwise>
|
||||||
|
</choose>
|
||||||
AND guacamole_entity.type = 'USER'
|
AND guacamole_entity.type = 'USER'
|
||||||
GROUP BY guacamole_user.user_id, guacamole_entity.entity_id;
|
GROUP BY guacamole_user.user_id, guacamole_entity.entity_id;
|
||||||
|
|
||||||
@@ -255,7 +326,14 @@
|
|||||||
JOIN guacamole_user ON guacamole_user.user_id = guacamole_user_attribute.user_id
|
JOIN guacamole_user ON guacamole_user.user_id = guacamole_user_attribute.user_id
|
||||||
JOIN guacamole_entity ON guacamole_user.entity_id = guacamole_entity.entity_id
|
JOIN guacamole_entity ON guacamole_user.entity_id = guacamole_entity.entity_id
|
||||||
WHERE
|
WHERE
|
||||||
guacamole_entity.name = #{username,jdbcType=VARCHAR}
|
<choose>
|
||||||
|
<when test="caseSensitive">
|
||||||
|
guacamole_entity.name = #{username,jdbcType=VARCHAR}
|
||||||
|
</when>
|
||||||
|
<otherwise>
|
||||||
|
LOWER(guacamole_entity.name) = LOWER(#{username,jdbcType=VARCHAR})
|
||||||
|
</otherwise>
|
||||||
|
</choose>
|
||||||
AND guacamole_entity.type = 'USER'
|
AND guacamole_entity.type = 'USER'
|
||||||
|
|
||||||
</select>
|
</select>
|
||||||
@@ -264,7 +342,14 @@
|
|||||||
<delete id="delete">
|
<delete id="delete">
|
||||||
DELETE FROM guacamole_entity
|
DELETE FROM guacamole_entity
|
||||||
WHERE
|
WHERE
|
||||||
name = #{identifier,jdbcType=VARCHAR}
|
<choose>
|
||||||
|
<when test="caseSensitive">
|
||||||
|
name = #{identifier,jdbcType=VARCHAR}
|
||||||
|
</when>
|
||||||
|
<otherwise>
|
||||||
|
LOWER(name) = LOWER(#{identifier,jdbcType=VARCHAR})
|
||||||
|
</otherwise>
|
||||||
|
</choose>
|
||||||
AND type = 'USER'
|
AND type = 'USER'
|
||||||
</delete>
|
</delete>
|
||||||
|
|
||||||
|
@@ -49,7 +49,14 @@
|
|||||||
(SELECT user_id FROM guacamole_user
|
(SELECT user_id FROM guacamole_user
|
||||||
JOIN guacamole_entity ON guacamole_user.entity_id = guacamole_entity.entity_id
|
JOIN guacamole_entity ON guacamole_user.entity_id = guacamole_entity.entity_id
|
||||||
WHERE
|
WHERE
|
||||||
guacamole_entity.name = #{record.username,jdbcType=VARCHAR}
|
<choose>
|
||||||
|
<when test="caseSensitive">
|
||||||
|
guacamole_entity.name = #{record.username,jdbcType=VARCHAR}
|
||||||
|
</when>
|
||||||
|
<otherwise>
|
||||||
|
LOWER(guacamole_entity.name) = LOWER(#{record.username,jdbcType=VARCHAR})
|
||||||
|
</otherwise>
|
||||||
|
</choose>
|
||||||
AND guacamole_entity.type = 'USER'),
|
AND guacamole_entity.type = 'USER'),
|
||||||
#{record.username,jdbcType=VARCHAR},
|
#{record.username,jdbcType=VARCHAR},
|
||||||
#{record.startDate,jdbcType=TIMESTAMP},
|
#{record.startDate,jdbcType=TIMESTAMP},
|
||||||
@@ -81,7 +88,14 @@
|
|||||||
<where>
|
<where>
|
||||||
|
|
||||||
<if test="identifier != null">
|
<if test="identifier != null">
|
||||||
guacamole_user_history.username = #{identifier,jdbcType=VARCHAR}
|
<choose>
|
||||||
|
<when test="caseSensitive">
|
||||||
|
guacamole_user_history.username = #{identifier,jdbcType=VARCHAR}
|
||||||
|
</when>
|
||||||
|
<otherwise>
|
||||||
|
LOWER(guacamole_user_history.username) = LOWER(#{identifier,jdbcType=VARCHAR})
|
||||||
|
</otherwise>
|
||||||
|
</choose>
|
||||||
</if>
|
</if>
|
||||||
|
|
||||||
<foreach collection="terms" item="term" open=" AND " separator=" AND ">
|
<foreach collection="terms" item="term" open=" AND " separator=" AND ">
|
||||||
@@ -92,7 +106,14 @@
|
|||||||
FROM guacamole_user
|
FROM guacamole_user
|
||||||
JOIN guacamole_entity ON guacamole_user.entity_id = guacamole_entity.entity_id
|
JOIN guacamole_entity ON guacamole_user.entity_id = guacamole_entity.entity_id
|
||||||
WHERE
|
WHERE
|
||||||
POSITION(#{term.term,jdbcType=VARCHAR} IN guacamole_entity.name) > 0
|
<choose>
|
||||||
|
<when test="caseSensitive">
|
||||||
|
POSITION(#{term.term,jdbcType=VARCHAR} IN guacamole_entity.name) > 0
|
||||||
|
</when>
|
||||||
|
<otherwise>
|
||||||
|
POSITION(LOWER(#{term.term,jdbcType=VARCHAR}) IN LOWER(guacamole_entity.name)) > 0
|
||||||
|
</otherwise>
|
||||||
|
</choose>
|
||||||
AND guacamole_entity.type = 'USER'),
|
AND guacamole_entity.type = 'USER'),
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -146,7 +167,15 @@
|
|||||||
)
|
)
|
||||||
|
|
||||||
<if test="identifier != null">
|
<if test="identifier != null">
|
||||||
AND guacamole_entity.name = #{identifier,jdbcType=VARCHAR}
|
AND
|
||||||
|
<choose>
|
||||||
|
<when test="caseSensitive">
|
||||||
|
guacamole_entity.name = #{identifier,jdbcType=VARCHAR}
|
||||||
|
</when>
|
||||||
|
<otherwise>
|
||||||
|
LOWER(guacamole_entity.name) = LOWER(#{identifier,jdbcType=VARCHAR})
|
||||||
|
</otherwise>
|
||||||
|
</choose>
|
||||||
</if>
|
</if>
|
||||||
|
|
||||||
<foreach collection="terms" item="term" open=" AND " separator=" AND ">
|
<foreach collection="terms" item="term" open=" AND " separator=" AND ">
|
||||||
@@ -157,7 +186,14 @@
|
|||||||
FROM guacamole_user
|
FROM guacamole_user
|
||||||
JOIN guacamole_entity ON guacamole_user.entity_id = guacamole_entity.entity_id
|
JOIN guacamole_entity ON guacamole_user.entity_id = guacamole_entity.entity_id
|
||||||
WHERE
|
WHERE
|
||||||
POSITION(#{term.term,jdbcType=VARCHAR} IN guacamole_entity.name) > 0
|
<choose>
|
||||||
|
<when test="caseSensitive">
|
||||||
|
POSITION(#{term.term,jdbcType=VARCHAR} IN guacamole_entity.name) > 0
|
||||||
|
</when>
|
||||||
|
<otherwise>
|
||||||
|
POSITION(LOWER(#{term.term,jdbcType=VARCHAR}) IN LOWER(guacamole_entity.name)) > 0
|
||||||
|
</otherwise>
|
||||||
|
</choose>
|
||||||
AND guacamole_entity.type = 'USER'
|
AND guacamole_entity.type = 'USER'
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@@ -58,10 +58,26 @@
|
|||||||
WHERE
|
WHERE
|
||||||
user_group_id = #{parent.objectID,jdbcType=INTEGER}
|
user_group_id = #{parent.objectID,jdbcType=INTEGER}
|
||||||
AND guacamole_entity.type = 'USER'
|
AND guacamole_entity.type = 'USER'
|
||||||
AND guacamole_entity.name IN
|
AND
|
||||||
|
<choose>
|
||||||
|
<when test="caseSensitive">
|
||||||
|
guacamole_entity.name
|
||||||
|
</when>
|
||||||
|
<otherwise>
|
||||||
|
LOWER(guacamole_entity.name)
|
||||||
|
</otherwise>
|
||||||
|
</choose>
|
||||||
|
IN
|
||||||
<foreach collection="children" item="identifier"
|
<foreach collection="children" item="identifier"
|
||||||
open="(" separator="," close=")">
|
open="(" separator="," close=")">
|
||||||
#{identifier,jdbcType=VARCHAR}
|
<choose>
|
||||||
|
<when test="caseSensitive">
|
||||||
|
#{identifier,jdbcType=VARCHAR}
|
||||||
|
</when>
|
||||||
|
<otherwise>
|
||||||
|
LOWER(#{identifier,jdbcType=VARCHAR})
|
||||||
|
</otherwise>
|
||||||
|
</choose>
|
||||||
</foreach>
|
</foreach>
|
||||||
</delete>
|
</delete>
|
||||||
|
|
||||||
@@ -76,10 +92,25 @@
|
|||||||
guacamole_entity.entity_id
|
guacamole_entity.entity_id
|
||||||
FROM guacamole_entity
|
FROM guacamole_entity
|
||||||
WHERE
|
WHERE
|
||||||
guacamole_entity.name IN
|
<choose>
|
||||||
|
<when test="caseSensitive">
|
||||||
|
guacamole_entity.name
|
||||||
|
</when>
|
||||||
|
<otherwise>
|
||||||
|
LOWER(guacamole_entity.name)
|
||||||
|
</otherwise>
|
||||||
|
</choose>
|
||||||
|
IN
|
||||||
<foreach collection="children" item="identifier"
|
<foreach collection="children" item="identifier"
|
||||||
open="(" separator="," close=")">
|
open="(" separator="," close=")">
|
||||||
#{identifier}
|
<choose>
|
||||||
|
<when test="caseSensitive">
|
||||||
|
#{identifier}
|
||||||
|
</when>
|
||||||
|
<otherwise>
|
||||||
|
LOWER(#{identifier})
|
||||||
|
</otherwise>
|
||||||
|
</choose>
|
||||||
</foreach>
|
</foreach>
|
||||||
AND guacamole_entity.type = 'USER'
|
AND guacamole_entity.type = 'USER'
|
||||||
AND guacamole_entity.entity_id NOT IN (
|
AND guacamole_entity.entity_id NOT IN (
|
||||||
|
@@ -399,4 +399,19 @@ public class PostgreSQLEnvironment extends JDBCEnvironment {
|
|||||||
true);
|
true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean getCaseSensitiveUsernames() throws GuacamoleException {
|
||||||
|
|
||||||
|
// By default, PostgreSQL does perform case-sensitive string comparisons.
|
||||||
|
// Even though usernames are generally not case-sensitive across
|
||||||
|
// most authenticaiton systems, we've elected to maintain case-
|
||||||
|
// sensitivity in this module in order to avoid surprising anyone who
|
||||||
|
// may be relying upon it.
|
||||||
|
return getProperty(
|
||||||
|
PostgreSQLGuacamoleProperties.POSTGRESQL_CASE_SENSITIVE_USERNAMES,
|
||||||
|
super.getCaseSensitiveUsernames()
|
||||||
|
);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -315,4 +315,16 @@ public class PostgreSQLGuacamoleProperties {
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A property used to configure whether or not usernames within the Postgres
|
||||||
|
* JDBC module should be treated as case-sensitive.
|
||||||
|
*/
|
||||||
|
public static final BooleanGuacamoleProperty POSTGRESQL_CASE_SENSITIVE_USERNAMES =
|
||||||
|
new BooleanGuacamoleProperty() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() { return "postgresql-case-sensitive-usernames"; }
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -61,7 +61,14 @@
|
|||||||
(SELECT user_id FROM guacamole_user
|
(SELECT user_id FROM guacamole_user
|
||||||
JOIN guacamole_entity ON guacamole_user.entity_id = guacamole_entity.entity_id
|
JOIN guacamole_entity ON guacamole_user.entity_id = guacamole_entity.entity_id
|
||||||
WHERE
|
WHERE
|
||||||
guacamole_entity.name = #{record.username,jdbcType=VARCHAR}
|
<choose>
|
||||||
|
<when test="caseSensitive">
|
||||||
|
guacamole_entity.name = #{record.username,jdbcType=VARCHAR}
|
||||||
|
</when>
|
||||||
|
<otherwise>
|
||||||
|
LOWER(guacamole_entity.name) = LOWER(#{record.username,jdbcType=VARCHAR})
|
||||||
|
</otherwise>
|
||||||
|
</choose>
|
||||||
AND guacamole_entity.type = 'USER'::guacamole_entity_type),
|
AND guacamole_entity.type = 'USER'::guacamole_entity_type),
|
||||||
#{record.username,jdbcType=VARCHAR},
|
#{record.username,jdbcType=VARCHAR},
|
||||||
#{record.startDate,jdbcType=TIMESTAMP},
|
#{record.startDate,jdbcType=TIMESTAMP},
|
||||||
@@ -110,7 +117,15 @@
|
|||||||
guacamole_connection_history.user_id IN (
|
guacamole_connection_history.user_id IN (
|
||||||
SELECT user_id
|
SELECT user_id
|
||||||
FROM guacamole_user
|
FROM guacamole_user
|
||||||
WHERE POSITION(#{term.term,jdbcType=VARCHAR} IN username) > 0
|
WHERE
|
||||||
|
<choose>
|
||||||
|
<when test="caseSensitive">
|
||||||
|
POSITION(#{term.term,jdbcType=VARCHAR} IN username) > 0
|
||||||
|
</when>
|
||||||
|
<otherwise>
|
||||||
|
POSITION(LOWER(#{term.term,jdbcType=VARCHAR}) IN LOWER(username)) > 0
|
||||||
|
</otherwise>
|
||||||
|
</choose>
|
||||||
)
|
)
|
||||||
|
|
||||||
OR guacamole_connection_history.connection_id IN (
|
OR guacamole_connection_history.connection_id IN (
|
||||||
@@ -198,7 +213,14 @@
|
|||||||
FROM guacamole_user
|
FROM guacamole_user
|
||||||
JOIN guacamole_entity ON guacamole_user.entity_id = guacamole_entity.entity_id
|
JOIN guacamole_entity ON guacamole_user.entity_id = guacamole_entity.entity_id
|
||||||
WHERE
|
WHERE
|
||||||
POSITION(#{term.term,jdbcType=VARCHAR} IN guacamole_entity.name) > 0
|
<choose>
|
||||||
|
<when test="caseSensitive">
|
||||||
|
POSITION(#{term.term,jdbcType=VARCHAR} IN guacamole_entity.name) > 0
|
||||||
|
</when>
|
||||||
|
<otherwise>
|
||||||
|
POSITION(LOWER(#{term.term,jdbcType=VARCHAR}) IN LOWER(guacamole_entity.name)) > 0
|
||||||
|
</otherwise>
|
||||||
|
</choose>
|
||||||
AND guacamole_entity.type = 'USER'::guacamole_entity_type
|
AND guacamole_entity.type = 'USER'::guacamole_entity_type
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@@ -28,7 +28,7 @@
|
|||||||
<result column="entity_id" property="entityID" jdbcType="INTEGER"/>
|
<result column="entity_id" property="entityID" jdbcType="INTEGER"/>
|
||||||
<result column="permission" property="type" jdbcType="VARCHAR"
|
<result column="permission" property="type" jdbcType="VARCHAR"
|
||||||
javaType="org.apache.guacamole.net.auth.permission.ObjectPermission$Type"/>
|
javaType="org.apache.guacamole.net.auth.permission.ObjectPermission$Type"/>
|
||||||
<result column="affected_name" property="objectIdentifier" jdbcType="INTEGER"/>
|
<result column="affected_name" property="objectIdentifier" jdbcType="VARCHAR"/>
|
||||||
</resultMap>
|
</resultMap>
|
||||||
|
|
||||||
<!-- Select all permissions for a given entity -->
|
<!-- Select all permissions for a given entity -->
|
||||||
@@ -68,7 +68,16 @@
|
|||||||
<property name="groups" value="effectiveGroups"/>
|
<property name="groups" value="effectiveGroups"/>
|
||||||
</include>
|
</include>
|
||||||
AND permission = #{type,jdbcType=VARCHAR}::guacamole_object_permission_type
|
AND permission = #{type,jdbcType=VARCHAR}::guacamole_object_permission_type
|
||||||
AND affected_entity.name = #{identifier,jdbcType=VARCHAR}
|
AND
|
||||||
|
<choose>
|
||||||
|
<when test="caseSensitive">
|
||||||
|
affected_entity.name = #{identifier,jdbcType=VARCHAR}
|
||||||
|
</when>
|
||||||
|
<otherwise>
|
||||||
|
LOWER(affected_entity.name) = LOWER(#{identifier,jdbcType=VARCHAR})
|
||||||
|
</otherwise>
|
||||||
|
</choose>
|
||||||
|
|
||||||
AND affected_entity.type = 'USER'::guacamole_entity_type
|
AND affected_entity.type = 'USER'::guacamole_entity_type
|
||||||
|
|
||||||
</select>
|
</select>
|
||||||
@@ -86,11 +95,23 @@
|
|||||||
<property name="entityID" value="#{entity.entityID,jdbcType=INTEGER}"/>
|
<property name="entityID" value="#{entity.entityID,jdbcType=INTEGER}"/>
|
||||||
<property name="groups" value="effectiveGroups"/>
|
<property name="groups" value="effectiveGroups"/>
|
||||||
</include>
|
</include>
|
||||||
AND affected_entity.name IN
|
AND
|
||||||
<foreach collection="identifiers" item="identifier"
|
<choose>
|
||||||
|
<when test="caseSensitive">
|
||||||
|
affected_entity.name IN
|
||||||
|
<foreach collection="identifiers" item="identifier"
|
||||||
open="(" separator="," close=")">
|
open="(" separator="," close=")">
|
||||||
#{identifier,jdbcType=VARCHAR}
|
#{identifier,jdbcType=VARCHAR}
|
||||||
</foreach>
|
</foreach>
|
||||||
|
</when>
|
||||||
|
<otherwise>
|
||||||
|
LOWER(affected_entity.name) IN
|
||||||
|
<foreach collection="identifiers" item="identifier"
|
||||||
|
open="(" separator="," close=")">
|
||||||
|
LOWER(#{identifier,jdbcType=VARCHAR})
|
||||||
|
</foreach>
|
||||||
|
</otherwise>
|
||||||
|
</choose>
|
||||||
AND permission IN
|
AND permission IN
|
||||||
<foreach collection="permissions" item="permission"
|
<foreach collection="permissions" item="permission"
|
||||||
open="(" separator="," close=")">
|
open="(" separator="," close=")">
|
||||||
@@ -108,13 +129,26 @@
|
|||||||
WHERE
|
WHERE
|
||||||
guacamole_user_permission.affected_user_id = affected_user.user_id
|
guacamole_user_permission.affected_user_id = affected_user.user_id
|
||||||
AND affected_user.entity_id = affected_entity.entity_id
|
AND affected_user.entity_id = affected_entity.entity_id
|
||||||
AND (guacamole_user_permission.entity_id, permission, affected_entity.name) IN
|
<choose>
|
||||||
<foreach collection="permissions" item="permission"
|
<when test="caseSensitive">
|
||||||
open="(" separator="," close=")">
|
AND (guacamole_user_permission.entity_id, permission, affected_entity.name) IN
|
||||||
(#{permission.entityID,jdbcType=INTEGER},
|
<foreach collection="permissions" item="permission"
|
||||||
#{permission.type,jdbcType=VARCHAR}::guacamole_object_permission_type,
|
open="(" separator="," close=")">
|
||||||
#{permission.objectIdentifier,jdbcType=INTEGER})
|
(#{permission.entityID,jdbcType=INTEGER},
|
||||||
</foreach>
|
#{permission.type,jdbcType=VARCHAR}::guacamole_object_permission_type,
|
||||||
|
#{permission.objectIdentifier,jdbcType=VARCHAR})
|
||||||
|
</foreach>
|
||||||
|
</when>
|
||||||
|
<otherwise>
|
||||||
|
AND (guacamole_user_permission.entity_id, permission, LOWER(affected_entity.name)) IN
|
||||||
|
<foreach collection="permissions" item="permission"
|
||||||
|
open="(" separator="," close=")">
|
||||||
|
(#{permission.entityID,jdbcType=INTEGER},
|
||||||
|
#{permission.type,jdbcType=VARCHAR}::guacamole_object_permission_type,
|
||||||
|
LOWER(#{permission.objectIdentifier,jdbcType=VARCHAR}))
|
||||||
|
</foreach>
|
||||||
|
</otherwise>
|
||||||
|
</choose>
|
||||||
AND affected_entity.type = 'USER'::guacamole_entity_type
|
AND affected_entity.type = 'USER'::guacamole_entity_type
|
||||||
|
|
||||||
</delete>
|
</delete>
|
||||||
@@ -140,7 +174,14 @@
|
|||||||
</foreach>
|
</foreach>
|
||||||
AS permissions
|
AS permissions
|
||||||
JOIN guacamole_entity affected_entity ON
|
JOIN guacamole_entity affected_entity ON
|
||||||
affected_entity.name = permissions.affected_name
|
<choose>
|
||||||
|
<when test="caseSensitive">
|
||||||
|
affected_entity.name = permissions.affected_name
|
||||||
|
</when>
|
||||||
|
<otherwise>
|
||||||
|
LOWER(affected_entity.name) = LOWER(permissions.affected_name)
|
||||||
|
</otherwise>
|
||||||
|
</choose>
|
||||||
AND affected_entity.type = 'USER'::guacamole_entity_type
|
AND affected_entity.type = 'USER'::guacamole_entity_type
|
||||||
JOIN guacamole_user affected_user ON affected_user.entity_id = affected_entity.entity_id
|
JOIN guacamole_user affected_user ON affected_user.entity_id = affected_entity.entity_id
|
||||||
WHERE (permissions.entity_id, permissions.permission, affected_user.user_id) NOT IN (
|
WHERE (permissions.entity_id, permissions.permission, affected_user.user_id) NOT IN (
|
||||||
|
@@ -43,7 +43,14 @@
|
|||||||
JOIN guacamole_user ON guacamole_user_password_history.user_id = guacamole_user.user_id
|
JOIN guacamole_user ON guacamole_user_password_history.user_id = guacamole_user.user_id
|
||||||
JOIN guacamole_entity ON guacamole_user.entity_id = guacamole_entity.entity_id
|
JOIN guacamole_entity ON guacamole_user.entity_id = guacamole_entity.entity_id
|
||||||
WHERE
|
WHERE
|
||||||
guacamole_entity.name = #{username,jdbcType=VARCHAR}
|
<choose>
|
||||||
|
<when test="caseSensitive">
|
||||||
|
guacamole_entity.name = #{username,jdbcType=VARCHAR}
|
||||||
|
</when>
|
||||||
|
<otherwise>
|
||||||
|
LOWER(guacamole_entity.name) = LOWER(#{username,jdbcType=VARCHAR})
|
||||||
|
</otherwise>
|
||||||
|
</choose>
|
||||||
ORDER BY
|
ORDER BY
|
||||||
guacamole_user_password_history.password_date DESC
|
guacamole_user_password_history.password_date DESC
|
||||||
LIMIT #{maxHistorySize}
|
LIMIT #{maxHistorySize}
|
||||||
|
@@ -130,10 +130,26 @@
|
|||||||
FROM guacamole_user
|
FROM guacamole_user
|
||||||
JOIN guacamole_entity ON guacamole_user.entity_id = guacamole_entity.entity_id
|
JOIN guacamole_entity ON guacamole_user.entity_id = guacamole_entity.entity_id
|
||||||
LEFT JOIN guacamole_user_history ON guacamole_user_history.user_id = guacamole_user.user_id
|
LEFT JOIN guacamole_user_history ON guacamole_user_history.user_id = guacamole_user.user_id
|
||||||
WHERE guacamole_entity.name IN
|
WHERE
|
||||||
|
<choose>
|
||||||
|
<when test="caseSensitive">
|
||||||
|
guacamole_entity.name
|
||||||
|
</when>
|
||||||
|
<otherwise>
|
||||||
|
LOWER(guacamole_entity.name)
|
||||||
|
</otherwise>
|
||||||
|
</choose>
|
||||||
|
IN
|
||||||
<foreach collection="identifiers" item="identifier"
|
<foreach collection="identifiers" item="identifier"
|
||||||
open="(" separator="," close=")">
|
open="(" separator="," close=")">
|
||||||
#{identifier,jdbcType=VARCHAR}
|
<choose>
|
||||||
|
<when test="caseSensitive">
|
||||||
|
#{identifier,jdbcType=VARCHAR}
|
||||||
|
</when>
|
||||||
|
<otherwise>
|
||||||
|
LOWER(#{identifier,jdbcType=VARCHAR})
|
||||||
|
</otherwise>
|
||||||
|
</choose>
|
||||||
</foreach>
|
</foreach>
|
||||||
AND guacamole_entity.type = 'USER'::guacamole_entity_type
|
AND guacamole_entity.type = 'USER'::guacamole_entity_type
|
||||||
GROUP BY guacamole_user.user_id, guacamole_entity.entity_id;
|
GROUP BY guacamole_user.user_id, guacamole_entity.entity_id;
|
||||||
@@ -145,10 +161,26 @@
|
|||||||
FROM guacamole_user_attribute
|
FROM guacamole_user_attribute
|
||||||
JOIN guacamole_user ON guacamole_user.user_id = guacamole_user_attribute.user_id
|
JOIN guacamole_user ON guacamole_user.user_id = guacamole_user_attribute.user_id
|
||||||
JOIN guacamole_entity ON guacamole_user.entity_id = guacamole_entity.entity_id
|
JOIN guacamole_entity ON guacamole_user.entity_id = guacamole_entity.entity_id
|
||||||
WHERE guacamole_entity.name IN
|
WHERE
|
||||||
|
<choose>
|
||||||
|
<when test="caseSensitive">
|
||||||
|
guacamole_entity.name
|
||||||
|
</when>
|
||||||
|
<otherwise>
|
||||||
|
LOWER(guacamole_entity.name)
|
||||||
|
</otherwise>
|
||||||
|
</choose>
|
||||||
|
IN
|
||||||
<foreach collection="identifiers" item="identifier"
|
<foreach collection="identifiers" item="identifier"
|
||||||
open="(" separator="," close=")">
|
open="(" separator="," close=")">
|
||||||
#{identifier,jdbcType=VARCHAR}
|
<choose>
|
||||||
|
<when test="caseSensitive">
|
||||||
|
#{identifier,jdbcType=VARCHAR}
|
||||||
|
</when>
|
||||||
|
<otherwise>
|
||||||
|
LOWER(#{identifier,jdbcType=VARCHAR})
|
||||||
|
</otherwise>
|
||||||
|
</choose>
|
||||||
</foreach>
|
</foreach>
|
||||||
AND guacamole_entity.type = 'USER'::guacamole_entity_type;
|
AND guacamole_entity.type = 'USER'::guacamole_entity_type;
|
||||||
|
|
||||||
@@ -180,10 +212,26 @@
|
|||||||
FROM guacamole_user
|
FROM guacamole_user
|
||||||
JOIN guacamole_entity ON guacamole_user.entity_id = guacamole_entity.entity_id
|
JOIN guacamole_entity ON guacamole_user.entity_id = guacamole_entity.entity_id
|
||||||
LEFT JOIN guacamole_user_history ON guacamole_user_history.user_id = guacamole_user.user_id
|
LEFT JOIN guacamole_user_history ON guacamole_user_history.user_id = guacamole_user.user_id
|
||||||
WHERE guacamole_entity.name IN
|
WHERE
|
||||||
|
<choose>
|
||||||
|
<when test="caseSensitive">
|
||||||
|
guacamole_entity.name
|
||||||
|
</when>
|
||||||
|
<otherwise>
|
||||||
|
LOWER(guacamole_entity.name)
|
||||||
|
</otherwise>
|
||||||
|
</choose>
|
||||||
|
IN
|
||||||
<foreach collection="identifiers" item="identifier"
|
<foreach collection="identifiers" item="identifier"
|
||||||
open="(" separator="," close=")">
|
open="(" separator="," close=")">
|
||||||
#{identifier,jdbcType=VARCHAR}
|
<choose>
|
||||||
|
<when test="caseSensitive">
|
||||||
|
#{identifier,jdbcType=VARCHAR}
|
||||||
|
</when>
|
||||||
|
<otherwise>
|
||||||
|
LOWER(#{identifier,jdbcType=VARCHAR})
|
||||||
|
</otherwise>
|
||||||
|
</choose>
|
||||||
</foreach>
|
</foreach>
|
||||||
AND guacamole_entity.type = 'USER'::guacamole_entity_type
|
AND guacamole_entity.type = 'USER'::guacamole_entity_type
|
||||||
AND guacamole_user.user_id IN (
|
AND guacamole_user.user_id IN (
|
||||||
@@ -201,10 +249,26 @@
|
|||||||
FROM guacamole_user_attribute
|
FROM guacamole_user_attribute
|
||||||
JOIN guacamole_user ON guacamole_user.user_id = guacamole_user_attribute.user_id
|
JOIN guacamole_user ON guacamole_user.user_id = guacamole_user_attribute.user_id
|
||||||
JOIN guacamole_entity ON guacamole_user.entity_id = guacamole_entity.entity_id
|
JOIN guacamole_entity ON guacamole_user.entity_id = guacamole_entity.entity_id
|
||||||
WHERE guacamole_entity.name IN
|
WHERE
|
||||||
|
<choose>
|
||||||
|
<when test="caseSensitive">
|
||||||
|
guacamole_entity.name
|
||||||
|
</when>
|
||||||
|
<otherwise>
|
||||||
|
LOWER(guacamole_entity.name)
|
||||||
|
</otherwise>
|
||||||
|
</choose>
|
||||||
|
IN
|
||||||
<foreach collection="identifiers" item="identifier"
|
<foreach collection="identifiers" item="identifier"
|
||||||
open="(" separator="," close=")">
|
open="(" separator="," close=")">
|
||||||
#{identifier,jdbcType=VARCHAR}
|
<choose>
|
||||||
|
<when test="caseSensitive">
|
||||||
|
#{identifier,jdbcType=VARCHAR}
|
||||||
|
</when>
|
||||||
|
<otherwise>
|
||||||
|
LOWER(#{identifier,jdbcType=VARCHAR})
|
||||||
|
</otherwise>
|
||||||
|
</choose>
|
||||||
</foreach>
|
</foreach>
|
||||||
AND guacamole_entity.type = 'USER'::guacamole_entity_type
|
AND guacamole_entity.type = 'USER'::guacamole_entity_type
|
||||||
AND guacamole_user.user_id IN (
|
AND guacamole_user.user_id IN (
|
||||||
@@ -243,7 +307,14 @@
|
|||||||
JOIN guacamole_entity ON guacamole_user.entity_id = guacamole_entity.entity_id
|
JOIN guacamole_entity ON guacamole_user.entity_id = guacamole_entity.entity_id
|
||||||
LEFT JOIN guacamole_user_history ON guacamole_user_history.user_id = guacamole_user.user_id
|
LEFT JOIN guacamole_user_history ON guacamole_user_history.user_id = guacamole_user.user_id
|
||||||
WHERE
|
WHERE
|
||||||
guacamole_entity.name = #{username,jdbcType=VARCHAR}
|
<choose>
|
||||||
|
<when test="caseSensitive">
|
||||||
|
guacamole_entity.name = #{username,jdbcType=VARCHAR}
|
||||||
|
</when>
|
||||||
|
<otherwise>
|
||||||
|
LOWER(guacamole_entity.name) = LOWER(#{username,jdbcType=VARCHAR})
|
||||||
|
</otherwise>
|
||||||
|
</choose>
|
||||||
AND guacamole_entity.type = 'USER'::guacamole_entity_type
|
AND guacamole_entity.type = 'USER'::guacamole_entity_type
|
||||||
GROUP BY guacamole_user.user_id, guacamole_entity.entity_id;
|
GROUP BY guacamole_user.user_id, guacamole_entity.entity_id;
|
||||||
|
|
||||||
@@ -255,16 +326,29 @@
|
|||||||
JOIN guacamole_user ON guacamole_user.user_id = guacamole_user_attribute.user_id
|
JOIN guacamole_user ON guacamole_user.user_id = guacamole_user_attribute.user_id
|
||||||
JOIN guacamole_entity ON guacamole_user.entity_id = guacamole_entity.entity_id
|
JOIN guacamole_entity ON guacamole_user.entity_id = guacamole_entity.entity_id
|
||||||
WHERE
|
WHERE
|
||||||
guacamole_entity.name = #{username,jdbcType=VARCHAR}
|
<choose>
|
||||||
|
<when test="caseSensitive">
|
||||||
|
guacamole_entity.name = #{username,jdbcType=VARCHAR}
|
||||||
|
</when>
|
||||||
|
<otherwise>
|
||||||
|
LOWER(guacamole_entity.name) = LOWER(#{username,jdbcType=VARCHAR})
|
||||||
|
</otherwise>
|
||||||
|
</choose>
|
||||||
AND guacamole_entity.type = 'USER'::guacamole_entity_type
|
AND guacamole_entity.type = 'USER'::guacamole_entity_type
|
||||||
|
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
<!-- Delete single user by username -->
|
<!-- Delete single user by username -->
|
||||||
<delete id="delete">
|
<delete id="delete">
|
||||||
DELETE FROM guacamole_entity
|
DELETE FROM guacamole_entity
|
||||||
WHERE
|
WHERE
|
||||||
name = #{identifier,jdbcType=VARCHAR}
|
<choose>
|
||||||
|
<when test="caseSensitive">
|
||||||
|
name = #{identifier,jdbcType=VARCHAR}
|
||||||
|
</when>
|
||||||
|
<otherwise>
|
||||||
|
LOWER(name) = LOWER(#{identifier,jdbcType=VARCHAR})
|
||||||
|
</otherwise>
|
||||||
|
</choose>
|
||||||
AND type = 'USER'::guacamole_entity_type
|
AND type = 'USER'::guacamole_entity_type
|
||||||
</delete>
|
</delete>
|
||||||
|
|
||||||
@@ -326,7 +410,7 @@
|
|||||||
email_address = #{object.emailAddress,jdbcType=VARCHAR},
|
email_address = #{object.emailAddress,jdbcType=VARCHAR},
|
||||||
organization = #{object.organization,jdbcType=VARCHAR},
|
organization = #{object.organization,jdbcType=VARCHAR},
|
||||||
organizational_role = #{object.organizationalRole,jdbcType=VARCHAR}
|
organizational_role = #{object.organizationalRole,jdbcType=VARCHAR}
|
||||||
WHERE user_id = #{object.objectID,jdbcType=VARCHAR}
|
WHERE user_id = #{object.objectID,jdbcType=INTEGER}
|
||||||
</update>
|
</update>
|
||||||
|
|
||||||
<!-- Delete attributes associated with user -->
|
<!-- Delete attributes associated with user -->
|
||||||
|
@@ -49,7 +49,14 @@
|
|||||||
(SELECT user_id FROM guacamole_user
|
(SELECT user_id FROM guacamole_user
|
||||||
JOIN guacamole_entity ON guacamole_user.entity_id = guacamole_entity.entity_id
|
JOIN guacamole_entity ON guacamole_user.entity_id = guacamole_entity.entity_id
|
||||||
WHERE
|
WHERE
|
||||||
guacamole_entity.name = #{record.username,jdbcType=VARCHAR}
|
<choose>
|
||||||
|
<when test="caseSensitive">
|
||||||
|
guacamole_entity.name = #{record.username,jdbcType=VARCHAR}
|
||||||
|
</when>
|
||||||
|
<otherwise>
|
||||||
|
LOWER(guacamole_entity.name) = LOWER(#{record.username,jdbcType=VARCHAR})
|
||||||
|
</otherwise>
|
||||||
|
</choose>
|
||||||
AND guacamole_entity.type = 'USER'::guacamole_entity_type),
|
AND guacamole_entity.type = 'USER'::guacamole_entity_type),
|
||||||
#{record.username,jdbcType=VARCHAR},
|
#{record.username,jdbcType=VARCHAR},
|
||||||
#{record.startDate,jdbcType=TIMESTAMP},
|
#{record.startDate,jdbcType=TIMESTAMP},
|
||||||
@@ -81,7 +88,14 @@
|
|||||||
<where>
|
<where>
|
||||||
|
|
||||||
<if test="identifier != null">
|
<if test="identifier != null">
|
||||||
guacamole_user_history.username = #{identifier,jdbcType=VARCHAR}
|
<choose>
|
||||||
|
<when test="caseSensitive">
|
||||||
|
guacamole_user_history.username = #{identifier,jdbcType=VARCHAR}
|
||||||
|
</when>
|
||||||
|
<otherwise>
|
||||||
|
LOWER(guacamole_user_history.username) = LOWER(#{identifier,jdbcType=VARCHAR})
|
||||||
|
</otherwise>
|
||||||
|
</choose>
|
||||||
</if>
|
</if>
|
||||||
|
|
||||||
<foreach collection="terms" item="term" open=" AND " separator=" AND ">
|
<foreach collection="terms" item="term" open=" AND " separator=" AND ">
|
||||||
@@ -92,7 +106,14 @@
|
|||||||
FROM guacamole_user
|
FROM guacamole_user
|
||||||
JOIN guacamole_entity ON guacamole_user.entity_id = guacamole_entity.entity_id
|
JOIN guacamole_entity ON guacamole_user.entity_id = guacamole_entity.entity_id
|
||||||
WHERE
|
WHERE
|
||||||
POSITION(#{term.term,jdbcType=VARCHAR} IN guacamole_entity.name) > 0
|
<choose>
|
||||||
|
<when test="caseSensitive">
|
||||||
|
POSITION(#{term.term,jdbcType=VARCHAR} IN guacamole_entity.name) > 0
|
||||||
|
</when>
|
||||||
|
<otherwise>
|
||||||
|
POSITION(LOWER(#{term.term,jdbcType=VARCHAR}) IN LOWER(guacamole_entity.name)) > 0
|
||||||
|
</otherwise>
|
||||||
|
</choose>
|
||||||
AND guacamole_entity.type = 'USER'::guacamole_entity_type),
|
AND guacamole_entity.type = 'USER'::guacamole_entity_type),
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -146,7 +167,15 @@
|
|||||||
)
|
)
|
||||||
|
|
||||||
<if test="identifier != null">
|
<if test="identifier != null">
|
||||||
AND guacamole_entity.name = #{identifier,jdbcType=VARCHAR}
|
AND
|
||||||
|
<choose>
|
||||||
|
<when test="caseSensitive">
|
||||||
|
guacamole_entity.name = #{identifier,jdbcType=VARCHAR}
|
||||||
|
</when>
|
||||||
|
<otherwise>
|
||||||
|
LOWER(guacamole_entity.name) = LOWER(#{identifier,jdbcType=VARCHAR})
|
||||||
|
</otherwise>
|
||||||
|
</choose>
|
||||||
</if>
|
</if>
|
||||||
|
|
||||||
<foreach collection="terms" item="term" open=" AND " separator=" AND ">
|
<foreach collection="terms" item="term" open=" AND " separator=" AND ">
|
||||||
@@ -157,7 +186,14 @@
|
|||||||
FROM guacamole_user
|
FROM guacamole_user
|
||||||
JOIN guacamole_entity ON guacamole_user.entity_id = guacamole_entity.entity_id
|
JOIN guacamole_entity ON guacamole_user.entity_id = guacamole_entity.entity_id
|
||||||
WHERE
|
WHERE
|
||||||
POSITION(#{term.term,jdbcType=VARCHAR} IN guacamole_entity.name) > 0
|
<choose>
|
||||||
|
<when test="caseSensitive">
|
||||||
|
POSITION(#{term.term,jdbcType=VARCHAR} IN guacamole_entity.name) > 0
|
||||||
|
</when>
|
||||||
|
<otherwise>
|
||||||
|
POSITION(LOWER(#{term.term,jdbcType=VARCHAR}) IN LOWER(guacamole_entity.name)) > 0
|
||||||
|
</otherwise>
|
||||||
|
</choose>
|
||||||
AND guacamole_entity.type = 'USER'::guacamole_entity_type
|
AND guacamole_entity.type = 'USER'::guacamole_entity_type
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@@ -58,11 +58,27 @@
|
|||||||
user_group_id = #{parent.objectID,jdbcType=INTEGER}
|
user_group_id = #{parent.objectID,jdbcType=INTEGER}
|
||||||
AND guacamole_entity.entity_id = member_entity_id
|
AND guacamole_entity.entity_id = member_entity_id
|
||||||
AND guacamole_entity.type = 'USER'::guacamole_entity_type
|
AND guacamole_entity.type = 'USER'::guacamole_entity_type
|
||||||
AND guacamole_entity.name IN
|
AND
|
||||||
<foreach collection="children" item="identifier"
|
<choose>
|
||||||
open="(" separator="," close=")">
|
<when test="caseSensitive">
|
||||||
#{identifier,jdbcType=VARCHAR}
|
guacamole_entity.name
|
||||||
</foreach>
|
</when>
|
||||||
|
<otherwise>
|
||||||
|
LOWER(guacamole_entity.name)
|
||||||
|
</otherwise>
|
||||||
|
</choose>
|
||||||
|
IN
|
||||||
|
<foreach collection="children" item="identifier"
|
||||||
|
open="(" separator="," close=")">
|
||||||
|
<choose>
|
||||||
|
<when test="caseSensitive">
|
||||||
|
#{identifier,jdbcType=VARCHAR}
|
||||||
|
</when>
|
||||||
|
<otherwise>
|
||||||
|
LOWER(#{identifier,jdbcType=VARCHAR})
|
||||||
|
</otherwise>
|
||||||
|
</choose>
|
||||||
|
</foreach>
|
||||||
</delete>
|
</delete>
|
||||||
|
|
||||||
<!-- Insert member users by name -->
|
<!-- Insert member users by name -->
|
||||||
@@ -76,11 +92,26 @@
|
|||||||
guacamole_entity.entity_id
|
guacamole_entity.entity_id
|
||||||
FROM guacamole_entity
|
FROM guacamole_entity
|
||||||
WHERE
|
WHERE
|
||||||
guacamole_entity.name IN
|
<choose>
|
||||||
<foreach collection="children" item="identifier"
|
<when test="caseSensitive">
|
||||||
open="(" separator="," close=")">
|
guacamole_entity.name
|
||||||
#{identifier}
|
</when>
|
||||||
</foreach>
|
<otherwise>
|
||||||
|
LOWER(guacamole_entity.name)
|
||||||
|
</otherwise>
|
||||||
|
</choose>
|
||||||
|
IN
|
||||||
|
<foreach collection="children" item="identifier"
|
||||||
|
open="(" separator="," close=")">
|
||||||
|
<choose>
|
||||||
|
<when test="caseSensitive">
|
||||||
|
#{identifier}
|
||||||
|
</when>
|
||||||
|
<otherwise>
|
||||||
|
LOWER(#{identifier})
|
||||||
|
</otherwise>
|
||||||
|
</choose>
|
||||||
|
</foreach>
|
||||||
AND guacamole_entity.type = 'USER'::guacamole_entity_type
|
AND guacamole_entity.type = 'USER'::guacamole_entity_type
|
||||||
AND guacamole_entity.entity_id NOT IN (
|
AND guacamole_entity.entity_id NOT IN (
|
||||||
SELECT guacamole_user_group_member.member_entity_id
|
SELECT guacamole_user_group_member.member_entity_id
|
||||||
|
@@ -329,4 +329,27 @@ public class SQLServerEnvironment extends JDBCEnvironment {
|
|||||||
false);
|
false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean getCaseSensitiveUsernames() throws GuacamoleException {
|
||||||
|
|
||||||
|
// Get the configured or default value of the property.
|
||||||
|
boolean caseSensitiveUsernames = getProperty(
|
||||||
|
SQLServerGuacamoleProperties.SQLSERVER_CASE_SENSITIVE_USERNAMES,
|
||||||
|
super.getCaseSensitiveUsernames()
|
||||||
|
);
|
||||||
|
|
||||||
|
// If property has been set to true, warn the admin.
|
||||||
|
if (caseSensitiveUsernames)
|
||||||
|
logger.warn("You have configured this extension for case-sensitive "
|
||||||
|
+ "username comparisons, however, the default collations "
|
||||||
|
+ "for SQL Server databases do not support case-sensitive "
|
||||||
|
+ "string comparisons. Further database configuration may "
|
||||||
|
+ "be required in order for case-sensitive username "
|
||||||
|
+ "comparisons to function correctly.");
|
||||||
|
|
||||||
|
// Return as configured
|
||||||
|
return caseSensitiveUsernames;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -258,4 +258,19 @@ public class SQLServerGuacamoleProperties {
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A property used to configure whether or not usernames within the SQL
|
||||||
|
* Server JDBC module should be treated as case-sensitive. While Guacamole
|
||||||
|
* will treat usernames as case-sensitive by default, SQL Server's default
|
||||||
|
* database collations do not do case-sensitive string comparisons, so in
|
||||||
|
* many cases this will effectively result in case-insensitive usernames.
|
||||||
|
*/
|
||||||
|
public static final BooleanGuacamoleProperty SQLSERVER_CASE_SENSITIVE_USERNAMES =
|
||||||
|
new BooleanGuacamoleProperty() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() { return "sqlserver-case-sensitive-usernames" ; }
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -68,7 +68,14 @@
|
|||||||
(SELECT user_id FROM [guacamole_user]
|
(SELECT user_id FROM [guacamole_user]
|
||||||
JOIN [guacamole_entity] ON [guacamole_user].entity_id = [guacamole_entity].entity_id
|
JOIN [guacamole_entity] ON [guacamole_user].entity_id = [guacamole_entity].entity_id
|
||||||
WHERE
|
WHERE
|
||||||
[guacamole_entity].name = #{record.username,jdbcType=VARCHAR}
|
<choose>
|
||||||
|
<when test="caseSensitive">
|
||||||
|
[guacamole_entity].name = #{record.username,jdbcType=VARCHAR}
|
||||||
|
</when>
|
||||||
|
<otherwise>
|
||||||
|
LOWER([guacamole_entity].name) = LOWER(#{record.username,jdbcType=VARCHAR})
|
||||||
|
</otherwise>
|
||||||
|
</choose>
|
||||||
AND [guacamole_entity].type = 'USER'),
|
AND [guacamole_entity].type = 'USER'),
|
||||||
#{record.username,jdbcType=VARCHAR},
|
#{record.username,jdbcType=VARCHAR},
|
||||||
#{record.startDate,jdbcType=TIMESTAMP},
|
#{record.startDate,jdbcType=TIMESTAMP},
|
||||||
@@ -110,7 +117,15 @@
|
|||||||
[guacamole_connection_history].user_id IN (
|
[guacamole_connection_history].user_id IN (
|
||||||
SELECT user_id
|
SELECT user_id
|
||||||
FROM [guacamole_user]
|
FROM [guacamole_user]
|
||||||
WHERE CHARINDEX(#{term.term,jdbcType=VARCHAR}, username) > 0
|
WHERE
|
||||||
|
<choose>
|
||||||
|
<when test="caseSensitive">
|
||||||
|
CHARINDEX(#{term.term,jdbcType=VARCHAR} IN username) > 0
|
||||||
|
</when>
|
||||||
|
<otherwise>
|
||||||
|
CHARINDEX(LOWER(#{term.term,jdbcType=VARCHAR}) IN LOWER(username)) > 0
|
||||||
|
</otherwise>
|
||||||
|
</choose>
|
||||||
)
|
)
|
||||||
|
|
||||||
OR [guacamole_connection_history].connection_id IN (
|
OR [guacamole_connection_history].connection_id IN (
|
||||||
@@ -196,7 +211,14 @@
|
|||||||
FROM [guacamole_user]
|
FROM [guacamole_user]
|
||||||
JOIN [guacamole_entity] ON [guacamole_user].entity_id = [guacamole_entity].entity_id
|
JOIN [guacamole_entity] ON [guacamole_user].entity_id = [guacamole_entity].entity_id
|
||||||
WHERE
|
WHERE
|
||||||
CHARINDEX(#{term.term,jdbcType=VARCHAR}, [guacamole_entity].name) > 0
|
<choose>
|
||||||
|
<hen test="caseSensitive">
|
||||||
|
CHARINDEX(#{term.term,jdbcType=VARCHAR} IN [guacamole_entity].name) > 0
|
||||||
|
</when>
|
||||||
|
<otherwise>
|
||||||
|
CHARINDEX(LOWER(#{term.term,jdbcType=VARCHAR}) IN LOWER(guacamole_entity.name)) > 0
|
||||||
|
</otherwise>
|
||||||
|
</choose>
|
||||||
AND [guacamole_entity].type = 'USER'
|
AND [guacamole_entity].type = 'USER'
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@@ -68,7 +68,15 @@
|
|||||||
<property name="groups" value="effectiveGroups"/>
|
<property name="groups" value="effectiveGroups"/>
|
||||||
</include>
|
</include>
|
||||||
AND permission = #{type,jdbcType=VARCHAR}
|
AND permission = #{type,jdbcType=VARCHAR}
|
||||||
AND affected_entity.name = #{identifier,jdbcType=VARCHAR}
|
AND
|
||||||
|
<choose>
|
||||||
|
<when test="caseSensitive">
|
||||||
|
affected_entity.name = #{identifier,jdbcType=VARCHAR}
|
||||||
|
</when>
|
||||||
|
<otherwise>
|
||||||
|
LOWER(affected_entity.name) = LOWER(#{identifier,jdbcType=VARCHAR})
|
||||||
|
</otherwise>
|
||||||
|
</choose>
|
||||||
AND affected_entity.type = 'USER'
|
AND affected_entity.type = 'USER'
|
||||||
|
|
||||||
</select>
|
</select>
|
||||||
@@ -86,11 +94,23 @@
|
|||||||
<property name="entityID" value="#{entity.entityID,jdbcType=INTEGER}"/>
|
<property name="entityID" value="#{entity.entityID,jdbcType=INTEGER}"/>
|
||||||
<property name="groups" value="effectiveGroups"/>
|
<property name="groups" value="effectiveGroups"/>
|
||||||
</include>
|
</include>
|
||||||
AND affected_entity.name IN
|
AND
|
||||||
<foreach collection="identifiers" item="identifier"
|
<choose>
|
||||||
|
<when test="caseSensitive">
|
||||||
|
affected_entity.name IN
|
||||||
|
<foreach collection="identifiers" item="identifier"
|
||||||
open="(" separator="," close=")">
|
open="(" separator="," close=")">
|
||||||
#{identifier,jdbcType=VARCHAR}
|
#{identifier,jdbcType=VARCHAR}
|
||||||
</foreach>
|
</foreach>
|
||||||
|
</when>
|
||||||
|
<otherwise>
|
||||||
|
LOWER(affected_entity.name) IN
|
||||||
|
<foreach collection="identifiers" item="identifier"
|
||||||
|
open="(" separator="," close=")">
|
||||||
|
LOWER(#{identifier,jdbcType=VARCHAR})
|
||||||
|
</foreach>
|
||||||
|
</otherwise>
|
||||||
|
</choose>
|
||||||
AND permission IN
|
AND permission IN
|
||||||
<foreach collection="permissions" item="permission"
|
<foreach collection="permissions" item="permission"
|
||||||
open="(" separator="," close=")">
|
open="(" separator="," close=")">
|
||||||
@@ -112,8 +132,16 @@
|
|||||||
open="(" separator=" OR " close=")">
|
open="(" separator=" OR " close=")">
|
||||||
([guacamole_user_permission].entity_id = #{permission.entityID,jdbcType=INTEGER} AND
|
([guacamole_user_permission].entity_id = #{permission.entityID,jdbcType=INTEGER} AND
|
||||||
permission = #{permission.type,jdbcType=VARCHAR} AND
|
permission = #{permission.type,jdbcType=VARCHAR} AND
|
||||||
affected_entity.name = #{permission.objectIdentifier,jdbcType=VARCHAR} AND
|
<choose>
|
||||||
affected_entity.type = 'USER')
|
<when test="caseSensitive">
|
||||||
|
affected_entity.name = #{permission.objectIdentifier,jdbcType=VARCHAR}
|
||||||
|
</when>
|
||||||
|
<otherwise>
|
||||||
|
LOWER(affected_entity.name = LOWER(#{permission.objectIdentifier,jdbcType=VARCHAR})
|
||||||
|
</otherwise>
|
||||||
|
</choose>
|
||||||
|
AND
|
||||||
|
affected_entity.type = 'USER')
|
||||||
</foreach>
|
</foreach>
|
||||||
|
|
||||||
</delete>
|
</delete>
|
||||||
@@ -139,7 +167,14 @@
|
|||||||
</foreach>
|
</foreach>
|
||||||
AS permissions
|
AS permissions
|
||||||
JOIN [guacamole_entity] affected_entity ON
|
JOIN [guacamole_entity] affected_entity ON
|
||||||
affected_entity.name = permissions.affected_name
|
<choose>
|
||||||
|
<when test="caseSensitive">
|
||||||
|
affected_entity.name = permissions.affected_name
|
||||||
|
</when>
|
||||||
|
<otherwise>
|
||||||
|
LOWER(affected_entity.name) = LOWER(permissions.affected_name)
|
||||||
|
</otherwise>
|
||||||
|
</choose>
|
||||||
AND affected_entity.type = 'USER'
|
AND affected_entity.type = 'USER'
|
||||||
JOIN [guacamole_user] affected_user ON affected_user.entity_id = affected_entity.entity_id
|
JOIN [guacamole_user] affected_user ON affected_user.entity_id = affected_entity.entity_id
|
||||||
WHERE NOT EXISTS (SELECT 1 FROM [guacamole_user_permission]
|
WHERE NOT EXISTS (SELECT 1 FROM [guacamole_user_permission]
|
||||||
|
@@ -43,7 +43,14 @@
|
|||||||
JOIN [guacamole_user] ON [guacamole_user_password_history].user_id = [guacamole_user].user_id
|
JOIN [guacamole_user] ON [guacamole_user_password_history].user_id = [guacamole_user].user_id
|
||||||
JOIN [guacamole_entity] ON [guacamole_user].entity_id = [guacamole_entity].entity_id
|
JOIN [guacamole_entity] ON [guacamole_user].entity_id = [guacamole_entity].entity_id
|
||||||
WHERE
|
WHERE
|
||||||
[guacamole_entity].name = #{username,jdbcType=VARCHAR}
|
<choose>
|
||||||
|
<when test="caseSensitive">
|
||||||
|
[guacamole_entity].name = #{username,jdbcType=VARCHAR}
|
||||||
|
</when>
|
||||||
|
<otherwise>
|
||||||
|
LOWER([guacamole_entity].name) = LOWER(#{username,jdbcType=VARCHAR})
|
||||||
|
</otherwise>
|
||||||
|
</choose>
|
||||||
ORDER BY
|
ORDER BY
|
||||||
[guacamole_user_password_history].password_date DESC
|
[guacamole_user_password_history].password_date DESC
|
||||||
|
|
||||||
|
@@ -133,10 +133,26 @@
|
|||||||
) AS last_active
|
) AS last_active
|
||||||
FROM [guacamole_user]
|
FROM [guacamole_user]
|
||||||
JOIN [guacamole_entity] ON [guacamole_user].entity_id = [guacamole_entity].entity_id
|
JOIN [guacamole_entity] ON [guacamole_user].entity_id = [guacamole_entity].entity_id
|
||||||
WHERE [guacamole_entity].name IN
|
WHERE
|
||||||
|
<choose>
|
||||||
|
<when test="caseSensitive">
|
||||||
|
[guacamole_entity].name
|
||||||
|
</when>
|
||||||
|
<otherwise>
|
||||||
|
LOWER([guacamole_entity].name)
|
||||||
|
</otherwise>
|
||||||
|
</choose>
|
||||||
|
IN
|
||||||
<foreach collection="identifiers" item="identifier"
|
<foreach collection="identifiers" item="identifier"
|
||||||
open="(" separator="," close=")">
|
open="(" separator="," close=")">
|
||||||
#{identifier,jdbcType=VARCHAR}
|
<choose>
|
||||||
|
<when test="caseSensitive">
|
||||||
|
#{identifier,jdbcType=VARCHAR}
|
||||||
|
</when>
|
||||||
|
<otherwise>
|
||||||
|
LOWER(#{identifier,jdbcType=VARCHAR})
|
||||||
|
</otherwise>
|
||||||
|
</choose>
|
||||||
</foreach>
|
</foreach>
|
||||||
AND [guacamole_entity].type = 'USER';
|
AND [guacamole_entity].type = 'USER';
|
||||||
|
|
||||||
@@ -147,10 +163,26 @@
|
|||||||
FROM [guacamole_user_attribute]
|
FROM [guacamole_user_attribute]
|
||||||
JOIN [guacamole_user] ON [guacamole_user].user_id = [guacamole_user_attribute].user_id
|
JOIN [guacamole_user] ON [guacamole_user].user_id = [guacamole_user_attribute].user_id
|
||||||
JOIN [guacamole_entity] ON [guacamole_user].entity_id = [guacamole_entity].entity_id
|
JOIN [guacamole_entity] ON [guacamole_user].entity_id = [guacamole_entity].entity_id
|
||||||
WHERE [guacamole_entity].name IN
|
WHERE
|
||||||
|
<choose>
|
||||||
|
<when test="caseSensitive">
|
||||||
|
[guacamole_entity].name
|
||||||
|
</when>
|
||||||
|
<otherwise>
|
||||||
|
LOWER([guacamole_entity].name)
|
||||||
|
</otherwise>
|
||||||
|
</choose>
|
||||||
|
IN
|
||||||
<foreach collection="identifiers" item="identifier"
|
<foreach collection="identifiers" item="identifier"
|
||||||
open="(" separator="," close=")">
|
open="(" separator="," close=")">
|
||||||
#{identifier,jdbcType=VARCHAR}
|
<choose>
|
||||||
|
<when test="caseSensitive">
|
||||||
|
#{identifier,jdbcType=VARCHAR}
|
||||||
|
</when>
|
||||||
|
<otherwise>
|
||||||
|
LOWER(#{identifier,jdbcType=VARCHAR})
|
||||||
|
</otherwise>
|
||||||
|
</choose>
|
||||||
</foreach>
|
</foreach>
|
||||||
AND [guacamole_entity].type = 'USER';
|
AND [guacamole_entity].type = 'USER';
|
||||||
|
|
||||||
@@ -185,10 +217,26 @@
|
|||||||
) AS last_active
|
) AS last_active
|
||||||
FROM [guacamole_user]
|
FROM [guacamole_user]
|
||||||
JOIN [guacamole_entity] ON [guacamole_user].entity_id = [guacamole_entity].entity_id
|
JOIN [guacamole_entity] ON [guacamole_user].entity_id = [guacamole_entity].entity_id
|
||||||
WHERE [guacamole_entity].name IN
|
WHERE
|
||||||
|
<choose>
|
||||||
|
<when test="caseSensitive">
|
||||||
|
[guacamole_entity].name
|
||||||
|
</when>
|
||||||
|
<otherwise>
|
||||||
|
LOWER([guacamole_entity].name)
|
||||||
|
</otherwise>
|
||||||
|
</choose>
|
||||||
|
IN
|
||||||
<foreach collection="identifiers" item="identifier"
|
<foreach collection="identifiers" item="identifier"
|
||||||
open="(" separator="," close=")">
|
open="(" separator="," close=")">
|
||||||
#{identifier,jdbcType=VARCHAR}
|
<choose>
|
||||||
|
<when test="caseSensitive">
|
||||||
|
#{identifier,jdbcType=VARCHAR}
|
||||||
|
</when>
|
||||||
|
<otherwise>
|
||||||
|
LOWER(#{identifier,jdbcType=VARCHAR})
|
||||||
|
</otherwise>
|
||||||
|
</choose>
|
||||||
</foreach>
|
</foreach>
|
||||||
AND [guacamole_entity].type = 'USER'
|
AND [guacamole_entity].type = 'USER'
|
||||||
AND [guacamole_user].user_id IN (
|
AND [guacamole_user].user_id IN (
|
||||||
@@ -205,10 +253,26 @@
|
|||||||
FROM [guacamole_user_attribute]
|
FROM [guacamole_user_attribute]
|
||||||
JOIN [guacamole_user] ON [guacamole_user].user_id = [guacamole_user_attribute].user_id
|
JOIN [guacamole_user] ON [guacamole_user].user_id = [guacamole_user_attribute].user_id
|
||||||
JOIN [guacamole_entity] ON [guacamole_user].entity_id = [guacamole_entity].entity_id
|
JOIN [guacamole_entity] ON [guacamole_user].entity_id = [guacamole_entity].entity_id
|
||||||
WHERE [guacamole_entity].name IN
|
WHERE
|
||||||
|
<choose>
|
||||||
|
<when test="caseSensitive">
|
||||||
|
[guacamole_entity].name
|
||||||
|
</when>
|
||||||
|
<otherwise>
|
||||||
|
LOWER([guacamole_entity].name)
|
||||||
|
</otherwise>
|
||||||
|
</choose>
|
||||||
|
IN
|
||||||
<foreach collection="identifiers" item="identifier"
|
<foreach collection="identifiers" item="identifier"
|
||||||
open="(" separator="," close=")">
|
open="(" separator="," close=")">
|
||||||
#{identifier,jdbcType=VARCHAR}
|
<choose>
|
||||||
|
<when test="caseSensitive">
|
||||||
|
#{identifier,jdbcType=VARCHAR}
|
||||||
|
</when>
|
||||||
|
<otherwise>
|
||||||
|
LOWER(#{identifier,jdbcType=VARCHAR})
|
||||||
|
</otherwise>
|
||||||
|
</choose>
|
||||||
</foreach>
|
</foreach>
|
||||||
AND [guacamole_entity].type = 'USER'
|
AND [guacamole_entity].type = 'USER'
|
||||||
AND [guacamole_user].user_id IN (
|
AND [guacamole_user].user_id IN (
|
||||||
@@ -250,7 +314,14 @@
|
|||||||
FROM [guacamole_user]
|
FROM [guacamole_user]
|
||||||
JOIN [guacamole_entity] ON [guacamole_user].entity_id = [guacamole_entity].entity_id
|
JOIN [guacamole_entity] ON [guacamole_user].entity_id = [guacamole_entity].entity_id
|
||||||
WHERE
|
WHERE
|
||||||
[guacamole_entity].name = #{username,jdbcType=VARCHAR}
|
<choose>
|
||||||
|
<when test="caseSensitive">
|
||||||
|
[guacamole_entity].name = #{username,jdbcType=VARCHAR}
|
||||||
|
</when>
|
||||||
|
<otherwise>
|
||||||
|
LOWER([guacamole_entity].name) = LOWER(#{username,jdbcType=VARCHAR})
|
||||||
|
</otherwise>
|
||||||
|
</choose>
|
||||||
AND [guacamole_entity].type = 'USER';
|
AND [guacamole_entity].type = 'USER';
|
||||||
|
|
||||||
SELECT
|
SELECT
|
||||||
@@ -261,7 +332,14 @@
|
|||||||
JOIN [guacamole_user] ON [guacamole_user].user_id = [guacamole_user_attribute].user_id
|
JOIN [guacamole_user] ON [guacamole_user].user_id = [guacamole_user_attribute].user_id
|
||||||
JOIN [guacamole_entity] ON [guacamole_user].entity_id = [guacamole_entity].entity_id
|
JOIN [guacamole_entity] ON [guacamole_user].entity_id = [guacamole_entity].entity_id
|
||||||
WHERE
|
WHERE
|
||||||
[guacamole_entity].name = #{username,jdbcType=VARCHAR}
|
<choose>
|
||||||
|
<when test="caseSensitive">
|
||||||
|
[guacamole_entity].name = #{username,jdbcType=VARCHAR}
|
||||||
|
</when>
|
||||||
|
<otherwise>
|
||||||
|
LOWER([guacamole_entity].name) = LOWER(#{username,jdbcType=VARCHAR})
|
||||||
|
</otherwise>
|
||||||
|
</choose>
|
||||||
AND [guacamole_entity].type = 'USER'
|
AND [guacamole_entity].type = 'USER'
|
||||||
|
|
||||||
</select>
|
</select>
|
||||||
@@ -270,7 +348,14 @@
|
|||||||
<delete id="delete">
|
<delete id="delete">
|
||||||
DELETE FROM [guacamole_entity]
|
DELETE FROM [guacamole_entity]
|
||||||
WHERE
|
WHERE
|
||||||
name = #{identifier,jdbcType=VARCHAR}
|
<choose>
|
||||||
|
<when test="caseSensitive">
|
||||||
|
name = #{identifier,jdbcType=VARCHAR}
|
||||||
|
</when>
|
||||||
|
<otherwise>
|
||||||
|
LOWER(name) = LOWER(#{identifier,jdbcType=VARCHAR})
|
||||||
|
</otherwise>
|
||||||
|
</choose>
|
||||||
AND type = 'USER'
|
AND type = 'USER'
|
||||||
</delete>
|
</delete>
|
||||||
|
|
||||||
@@ -332,7 +417,7 @@
|
|||||||
email_address = #{object.emailAddress,jdbcType=VARCHAR},
|
email_address = #{object.emailAddress,jdbcType=VARCHAR},
|
||||||
organization = #{object.organization,jdbcType=VARCHAR},
|
organization = #{object.organization,jdbcType=VARCHAR},
|
||||||
organizational_role = #{object.organizationalRole,jdbcType=VARCHAR}
|
organizational_role = #{object.organizationalRole,jdbcType=VARCHAR}
|
||||||
WHERE user_id = #{object.objectID,jdbcType=VARCHAR}
|
WHERE user_id = #{object.objectID,jdbcType=INTEGER}
|
||||||
</update>
|
</update>
|
||||||
|
|
||||||
<!-- Delete attributes associated with user -->
|
<!-- Delete attributes associated with user -->
|
||||||
|
@@ -49,8 +49,15 @@
|
|||||||
(SELECT user_id FROM [guacamole_user]
|
(SELECT user_id FROM [guacamole_user]
|
||||||
JOIN [guacamole_entity] ON [guacamole_user].entity_id = [guacamole_entity].entity_id
|
JOIN [guacamole_entity] ON [guacamole_user].entity_id = [guacamole_entity].entity_id
|
||||||
WHERE
|
WHERE
|
||||||
[guacamole_entity].name = #{record.username,jdbcType=VARCHAR}
|
<choose>
|
||||||
AND [guacamole_entity].type = 'USER'),
|
<when test="caseSensitive">
|
||||||
|
[guacamole_entity].name = #{record.username,jdbcType=VARCHAR}
|
||||||
|
</when>
|
||||||
|
<otherwise>
|
||||||
|
LOWER([guacamole_entity].name) = LOWER(#{record.username,jdbcType=VARCHAR})
|
||||||
|
</otherwise>
|
||||||
|
</choose>
|
||||||
|
AND [guacamole_entity].type = 'USER'),
|
||||||
#{record.username,jdbcType=VARCHAR},
|
#{record.username,jdbcType=VARCHAR},
|
||||||
#{record.startDate,jdbcType=TIMESTAMP},
|
#{record.startDate,jdbcType=TIMESTAMP},
|
||||||
#{record.endDate,jdbcType=TIMESTAMP}
|
#{record.endDate,jdbcType=TIMESTAMP}
|
||||||
@@ -81,7 +88,14 @@
|
|||||||
<where>
|
<where>
|
||||||
|
|
||||||
<if test="identifier != null">
|
<if test="identifier != null">
|
||||||
[guacamole_user_history].username = #{identifier,jdbcType=VARCHAR}
|
<choose>
|
||||||
|
<when test="caseSensitive">
|
||||||
|
[guacamole_user_history].username = #{identifier,jdbcType=VARCHAR}
|
||||||
|
</when>
|
||||||
|
<otherwise>
|
||||||
|
LOWER([guacamole_user_history].username) = LOWER(#{identifier,jdbcType=VARCHAR})
|
||||||
|
</otherwise>
|
||||||
|
</choose>
|
||||||
</if>
|
</if>
|
||||||
|
|
||||||
<foreach collection="terms" item="term" open=" AND " separator=" AND ">
|
<foreach collection="terms" item="term" open=" AND " separator=" AND ">
|
||||||
@@ -92,7 +106,14 @@
|
|||||||
FROM [guacamole_user]
|
FROM [guacamole_user]
|
||||||
JOIN [guacamole_entity] ON [guacamole_user].entity_id = [guacamole_entity].entity_id
|
JOIN [guacamole_entity] ON [guacamole_user].entity_id = [guacamole_entity].entity_id
|
||||||
WHERE
|
WHERE
|
||||||
CHARINDEX(#{term.term,jdbcType=VARCHAR}, [guacamole_entity].name) > 0
|
<choose>
|
||||||
|
<when test="caseSensitive">
|
||||||
|
CHARINDEX(#{term.term,jdbcType=VARCHAR} IN [guacamole_entity].name) > 0
|
||||||
|
</when>
|
||||||
|
<otherwise>
|
||||||
|
CHARINDEX(LOWER(#{term.term,jdbcType=VARCHAR}) IN LOWER([guacamole_entity].name)) > 0
|
||||||
|
</otherwise>
|
||||||
|
</choose>
|
||||||
AND [guacamole_entity].type = 'USER'),
|
AND [guacamole_entity].type = 'USER'),
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -144,7 +165,15 @@
|
|||||||
)
|
)
|
||||||
|
|
||||||
<if test="identifier != null">
|
<if test="identifier != null">
|
||||||
AND [guacamole_entity].name = #{identifier,jdbcType=VARCHAR}
|
AND
|
||||||
|
<choose>
|
||||||
|
<when test="caseSensitive">
|
||||||
|
[guacamole_entity].name = #{identifier,jdbcType=VARCHAR}
|
||||||
|
</when>
|
||||||
|
<otherwise>
|
||||||
|
LOWER([guacamole_entity].name) = LOWER(#{identifier,jdbcType=VARCHAR})
|
||||||
|
</otherwise>
|
||||||
|
</choose>
|
||||||
</if>
|
</if>
|
||||||
|
|
||||||
<foreach collection="terms" item="term" open=" AND " separator=" AND ">
|
<foreach collection="terms" item="term" open=" AND " separator=" AND ">
|
||||||
@@ -155,7 +184,14 @@
|
|||||||
FROM [guacamole_user]
|
FROM [guacamole_user]
|
||||||
JOIN [guacamole_entity] ON [guacamole_user].entity_id = [guacamole_entity].entity_id
|
JOIN [guacamole_entity] ON [guacamole_user].entity_id = [guacamole_entity].entity_id
|
||||||
WHERE
|
WHERE
|
||||||
CHARINDEX(#{term.term,jdbcType=VARCHAR}, [guacamole_entity].name) > 0
|
<choose>
|
||||||
|
<when test="caseSensitive">
|
||||||
|
CHARINDEX(#{term.term,jdbcType=VARCHAR} IN [guacamole_entity].name) > 0
|
||||||
|
</when>
|
||||||
|
<otherwise>
|
||||||
|
CHARINDEX(LOWER(#{term.term,jdbcType=VARCHAR}) IN LOWER([guacamole_entity].name)) > 0
|
||||||
|
</otherwise>
|
||||||
|
</choose>
|
||||||
AND [guacamole_entity].type = 'USER'
|
AND [guacamole_entity].type = 'USER'
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@@ -58,11 +58,27 @@
|
|||||||
WHERE
|
WHERE
|
||||||
user_group_id = #{parent.objectID,jdbcType=INTEGER}
|
user_group_id = #{parent.objectID,jdbcType=INTEGER}
|
||||||
AND [guacamole_entity].type = 'USER'
|
AND [guacamole_entity].type = 'USER'
|
||||||
AND [guacamole_entity].name IN
|
AND
|
||||||
<foreach collection="children" item="identifier"
|
<choose>
|
||||||
open="(" separator="," close=")">
|
<when test="caseSensitive">
|
||||||
#{identifier,jdbcType=VARCHAR}
|
[guacamole_entity].name
|
||||||
</foreach>
|
</when>
|
||||||
|
<otherwise>
|
||||||
|
LOWER([guacamole_entity].name)
|
||||||
|
</otherwise>
|
||||||
|
</choose>
|
||||||
|
IN
|
||||||
|
<foreach collection="children" item="identifier"
|
||||||
|
open="(" separator="," close=")">
|
||||||
|
<choose>
|
||||||
|
<when test="caseSensitive">
|
||||||
|
#{identifier,jdbcType=VARCHAR}
|
||||||
|
</when>
|
||||||
|
<otherwise>
|
||||||
|
LOWER(#{identifier,jdbcType=VARCHAR})
|
||||||
|
</otherwise>
|
||||||
|
</choose>
|
||||||
|
</foreach>
|
||||||
</delete>
|
</delete>
|
||||||
|
|
||||||
<!-- Insert member users by name -->
|
<!-- Insert member users by name -->
|
||||||
@@ -76,11 +92,26 @@
|
|||||||
[guacamole_entity].entity_id
|
[guacamole_entity].entity_id
|
||||||
FROM [guacamole_entity]
|
FROM [guacamole_entity]
|
||||||
WHERE
|
WHERE
|
||||||
[guacamole_entity].name IN
|
<choose>
|
||||||
<foreach collection="children" item="identifier"
|
<when test="caseSensitive">
|
||||||
open="(" separator="," close=")">
|
[guacamole_entity].name
|
||||||
#{identifier}
|
</when>
|
||||||
</foreach>
|
<otherwise>
|
||||||
|
LOWER([guacamole_entity].name)
|
||||||
|
</otherwise>
|
||||||
|
</choose>
|
||||||
|
IN
|
||||||
|
<foreach collection="children" item="identifier"
|
||||||
|
open="(" separator="," close=")">
|
||||||
|
<choose>
|
||||||
|
<when test="caseSensitive">
|
||||||
|
#{identifier}
|
||||||
|
</when>
|
||||||
|
<otherwise>
|
||||||
|
LOWER(#{identifier})
|
||||||
|
</otherwise>
|
||||||
|
</choose>
|
||||||
|
</foreach>
|
||||||
AND [guacamole_entity].type = 'USER'
|
AND [guacamole_entity].type = 'USER'
|
||||||
AND [guacamole_entity].entity_id NOT IN (
|
AND [guacamole_entity].entity_id NOT IN (
|
||||||
SELECT [guacamole_user_group_member].member_entity_id
|
SELECT [guacamole_user_group_member].member_entity_id
|
||||||
|
@@ -24,6 +24,7 @@ import java.util.Collection;
|
|||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import org.apache.guacamole.GuacamoleException;
|
import org.apache.guacamole.GuacamoleException;
|
||||||
import org.apache.guacamole.environment.Environment;
|
import org.apache.guacamole.environment.Environment;
|
||||||
|
import org.apache.guacamole.properties.BooleanGuacamoleProperty;
|
||||||
import org.apache.guacamole.properties.ByteArrayProperty;
|
import org.apache.guacamole.properties.ByteArrayProperty;
|
||||||
import org.apache.guacamole.properties.StringGuacamoleProperty;
|
import org.apache.guacamole.properties.StringGuacamoleProperty;
|
||||||
|
|
||||||
@@ -39,6 +40,20 @@ public class ConfigurationService {
|
|||||||
@Inject
|
@Inject
|
||||||
private Environment environment;
|
private Environment environment;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A property used to configure whether or not usernames within the JSON
|
||||||
|
* module should be treated as case-sensitive.
|
||||||
|
*/
|
||||||
|
private static final BooleanGuacamoleProperty JSON_CASE_SENSITIVE_USERNAMES =
|
||||||
|
new BooleanGuacamoleProperty() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return "json-case-sensitive-usernames";
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The encryption key to use for all decryption and signature verification.
|
* The encryption key to use for all decryption and signature verification.
|
||||||
*/
|
*/
|
||||||
@@ -65,6 +80,25 @@ public class ConfigurationService {
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if the usernames provided to the JSON authentication
|
||||||
|
* module should be treated as case-sensitive, or false if usernames
|
||||||
|
* should be treated as case-insensitive. The default will be taken from
|
||||||
|
* the global Guacamole configuration, which defaults to true, but
|
||||||
|
* can be overridden for this extension.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* true if usernames should be treated as case-sensitive, otherwise
|
||||||
|
* false.
|
||||||
|
*
|
||||||
|
* @throws GuacamoleException
|
||||||
|
* If guacamole.properties cannot be parsed.
|
||||||
|
*/
|
||||||
|
public boolean getCaseSensitiveUsernames() throws GuacamoleException {
|
||||||
|
return environment.getProperty(JSON_CASE_SENSITIVE_USERNAMES,
|
||||||
|
environment.getCaseSensitiveUsernames());
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the symmetric key which will be used to encrypt and sign all
|
* Returns the symmetric key which will be used to encrypt and sign all
|
||||||
* JSON data and should be used to decrypt and verify any received JSON
|
* JSON data and should be used to decrypt and verify any received JSON
|
||||||
|
@@ -20,9 +20,13 @@
|
|||||||
package org.apache.guacamole.auth.json.user;
|
package org.apache.guacamole.auth.json.user;
|
||||||
|
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
|
import org.apache.guacamole.GuacamoleException;
|
||||||
|
import org.apache.guacamole.auth.json.ConfigurationService;
|
||||||
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;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An implementation of AuthenticatedUser specific to the
|
* An implementation of AuthenticatedUser specific to the
|
||||||
@@ -31,6 +35,11 @@ import org.apache.guacamole.net.auth.Credentials;
|
|||||||
*/
|
*/
|
||||||
public class AuthenticatedUser extends AbstractAuthenticatedUser {
|
public class AuthenticatedUser extends AbstractAuthenticatedUser {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Logger for this class.
|
||||||
|
*/
|
||||||
|
private static final Logger LOGGER = LoggerFactory.getLogger(AuthenticatedUser.class);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reference to the authentication provider associated with this
|
* Reference to the authentication provider associated with this
|
||||||
* authenticated user.
|
* authenticated user.
|
||||||
@@ -38,6 +47,13 @@ public class AuthenticatedUser extends AbstractAuthenticatedUser {
|
|||||||
@Inject
|
@Inject
|
||||||
private AuthenticationProvider authProvider;
|
private AuthenticationProvider authProvider;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reference to the configuration service associated with this
|
||||||
|
* authentication provider.
|
||||||
|
*/
|
||||||
|
@Inject
|
||||||
|
private ConfigurationService confService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The credentials provided when this user was authenticated.
|
* The credentials provided when this user was authenticated.
|
||||||
*/
|
*/
|
||||||
@@ -67,6 +83,19 @@ public class AuthenticatedUser extends AbstractAuthenticatedUser {
|
|||||||
setIdentifier(userData.getUsername());
|
setIdentifier(userData.getUsername());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isCaseSensitive() {
|
||||||
|
try {
|
||||||
|
return confService.getCaseSensitiveUsernames();
|
||||||
|
}
|
||||||
|
catch (GuacamoleException e) {
|
||||||
|
LOGGER.error("Error when attempting to get the JSON configuration: {}. "
|
||||||
|
+ "Username comparisons will be case-sensitive.", e.getMessage());
|
||||||
|
LOGGER.debug("Exception caught while retrieving JSON configuration.", e);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public AuthenticationProvider getAuthenticationProvider() {
|
public AuthenticationProvider getAuthenticationProvider() {
|
||||||
return authProvider;
|
return authProvider;
|
||||||
|
@@ -224,4 +224,9 @@ public class ConnectedLDAPConfiguration implements LDAPConfiguration, AutoClosea
|
|||||||
return config.getMemberAttributeType();
|
return config.getMemberAttributeType();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean getCaseSensitiveUsernames() throws GuacamoleException {
|
||||||
|
return config.getCaseSensitiveUsernames();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -19,6 +19,7 @@
|
|||||||
|
|
||||||
package org.apache.guacamole.auth.ldap.conf;
|
package org.apache.guacamole.auth.ldap.conf;
|
||||||
|
|
||||||
|
import com.google.inject.Inject;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import org.apache.directory.api.ldap.model.filter.ExprNode;
|
import org.apache.directory.api.ldap.model.filter.ExprNode;
|
||||||
@@ -27,6 +28,7 @@ import org.apache.directory.api.ldap.model.message.AliasDerefMode;
|
|||||||
import org.apache.directory.api.ldap.model.name.Dn;
|
import org.apache.directory.api.ldap.model.name.Dn;
|
||||||
import org.apache.guacamole.GuacamoleException;
|
import org.apache.guacamole.GuacamoleException;
|
||||||
import org.apache.guacamole.GuacamoleServerException;
|
import org.apache.guacamole.GuacamoleServerException;
|
||||||
|
import org.apache.guacamole.environment.Environment;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* LDAPConfiguration implementation that returns the default values for all
|
* LDAPConfiguration implementation that returns the default values for all
|
||||||
@@ -35,6 +37,12 @@ import org.apache.guacamole.GuacamoleServerException;
|
|||||||
*/
|
*/
|
||||||
public class DefaultLDAPConfiguration implements LDAPConfiguration {
|
public class DefaultLDAPConfiguration implements LDAPConfiguration {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The environment in which Guacamole is running.
|
||||||
|
*/
|
||||||
|
@Inject
|
||||||
|
private Environment environment;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String appliesTo(String username) {
|
public String appliesTo(String username) {
|
||||||
return null;
|
return null;
|
||||||
@@ -151,4 +159,9 @@ public class DefaultLDAPConfiguration implements LDAPConfiguration {
|
|||||||
return MemberAttributeType.DN;
|
return MemberAttributeType.DN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean getCaseSensitiveUsernames() throws GuacamoleException {
|
||||||
|
return environment.getCaseSensitiveUsernames();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -234,4 +234,18 @@ public class EnvironmentLDAPConfiguration implements LDAPConfiguration {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean getCaseSensitiveUsernames() throws GuacamoleException {
|
||||||
|
|
||||||
|
// Most LDAP directories do not factor in case when comparing usernames,
|
||||||
|
// however, in order to avoid surprising anyone who may rely on this
|
||||||
|
// behavior in Guacamole, this is currently defaulted the overall
|
||||||
|
// Guacamole configuration (default of true), but can be over-ridden
|
||||||
|
// for the LDAP extension specifically, if desired.
|
||||||
|
return environment.getProperty(
|
||||||
|
LDAPGuacamoleProperties.LDAP_CASE_SENSITIVE_USERNAMES,
|
||||||
|
environment.getCaseSensitiveUsernames()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -204,6 +204,13 @@ public class JacksonLDAPConfiguration implements LDAPConfiguration {
|
|||||||
@JsonProperty("member-attribute-type")
|
@JsonProperty("member-attribute-type")
|
||||||
private String memberAttributeType;
|
private String memberAttributeType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The raw YAML value of {@link LDAPGuacamoleProperties#LDAP_USERNAMES_CASE_SENSITIVE}.
|
||||||
|
* If not set within the YAML, this will currently default to true.
|
||||||
|
*/
|
||||||
|
@JsonProperty("case-sensitive-usernames")
|
||||||
|
private String caseSensitiveUsernames;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The default configuration options for all parameters.
|
* The default configuration options for all parameters.
|
||||||
*/
|
*/
|
||||||
@@ -440,4 +447,10 @@ public class JacksonLDAPConfiguration implements LDAPConfiguration {
|
|||||||
memberAttributeType, defaultConfig::getMemberAttributeType);
|
memberAttributeType, defaultConfig::getMemberAttributeType);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean getCaseSensitiveUsernames() throws GuacamoleException {
|
||||||
|
return withDefault(LDAPGuacamoleProperties.LDAP_CASE_SENSITIVE_USERNAMES,
|
||||||
|
caseSensitiveUsernames, defaultConfig::getCaseSensitiveUsernames);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -20,7 +20,6 @@
|
|||||||
package org.apache.guacamole.auth.ldap.conf;
|
package org.apache.guacamole.auth.ldap.conf;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
|
||||||
import org.apache.directory.api.ldap.model.filter.ExprNode;
|
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.message.AliasDerefMode;
|
||||||
import org.apache.directory.api.ldap.model.name.Dn;
|
import org.apache.directory.api.ldap.model.name.Dn;
|
||||||
@@ -335,4 +334,20 @@ public interface LDAPConfiguration {
|
|||||||
*/
|
*/
|
||||||
MemberAttributeType getMemberAttributeType() throws GuacamoleException;
|
MemberAttributeType getMemberAttributeType() throws GuacamoleException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if the usernames provided to the LDAP authentication
|
||||||
|
* module should be treated as case-sensitive, or false if usernames
|
||||||
|
* should be treated as case-insensitive. The default is true, usernames
|
||||||
|
* will be case-sensitive in keeping with the past behavior of Guacamole
|
||||||
|
* prior to the addition of this option.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* true if usernames should be treated as case-sensitive, otherwise
|
||||||
|
* false.
|
||||||
|
*
|
||||||
|
* @throws GuacamoleException
|
||||||
|
* If guacamole.properties cannot be parsed.
|
||||||
|
*/
|
||||||
|
boolean getCaseSensitiveUsernames() throws GuacamoleException;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -307,4 +307,16 @@ public class LDAPGuacamoleProperties {
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A property used to configure whether or not usernames within the LDAP
|
||||||
|
* module should be treated as case-sensitive.
|
||||||
|
*/
|
||||||
|
public static final BooleanGuacamoleProperty LDAP_CASE_SENSITIVE_USERNAMES =
|
||||||
|
new BooleanGuacamoleProperty() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() { return "ldap-case-sensitive-usernames"; }
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -24,10 +24,13 @@ 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.GuacamoleException;
|
||||||
import org.apache.guacamole.auth.ldap.ConnectedLDAPConfiguration;
|
import org.apache.guacamole.auth.ldap.ConnectedLDAPConfiguration;
|
||||||
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;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An LDAP-specific implementation of AuthenticatedUser, associating a
|
* An LDAP-specific implementation of AuthenticatedUser, associating a
|
||||||
@@ -35,6 +38,11 @@ import org.apache.guacamole.net.auth.Credentials;
|
|||||||
*/
|
*/
|
||||||
public class LDAPAuthenticatedUser extends AbstractAuthenticatedUser {
|
public class LDAPAuthenticatedUser extends AbstractAuthenticatedUser {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The logger for this class.
|
||||||
|
*/
|
||||||
|
private static final Logger LOGGER = LoggerFactory.getLogger(LDAPAuthenticatedUser.class);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reference to the authentication provider associated with this
|
* Reference to the authentication provider associated with this
|
||||||
* authenticated user.
|
* authenticated user.
|
||||||
@@ -135,6 +143,23 @@ public class LDAPAuthenticatedUser extends AbstractAuthenticatedUser {
|
|||||||
return config;
|
return config;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isCaseSensitive() {
|
||||||
|
try {
|
||||||
|
return config.getCaseSensitiveUsernames();
|
||||||
|
}
|
||||||
|
catch (GuacamoleException e) {
|
||||||
|
// LDAP authentication is almost universally case-insensitive,
|
||||||
|
// however, we're maintaining case-sensitivity within Guacamole
|
||||||
|
// at the moment in order to avoid surprising anyone with this change.
|
||||||
|
// Case-sensitivity can be disabled as a configuration option.
|
||||||
|
LOGGER.error("Error retrieving configuration for username case-sensitivity: {}. "
|
||||||
|
+ "Username comparisons will be done case-sensitively.", e.getMessage());
|
||||||
|
LOGGER.debug("Caught exception when retrieving case-sensitivity configuration.", e);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public AuthenticationProvider getAuthenticationProvider() {
|
public AuthenticationProvider getAuthenticationProvider() {
|
||||||
return authProvider;
|
return authProvider;
|
||||||
|
@@ -363,4 +363,25 @@ public class ConfigurationService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if the usernames provided to the RADIUS authentication
|
||||||
|
* module should be treated as case-sensitive, or false if usernames
|
||||||
|
* should be treated as case-insensitive. The default value is read from
|
||||||
|
* Guacamole's global configuration, which defaults to true, but can be
|
||||||
|
* overridden for the RADIUS extension, if desired.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* true if usernames should be treated as case-sensitive, otherwise
|
||||||
|
* false.
|
||||||
|
*
|
||||||
|
* @throws GuacamoleException
|
||||||
|
* If guacamole.properties cannot be parsed.
|
||||||
|
*/
|
||||||
|
public boolean getCaseSensitiveUsernames() throws GuacamoleException {
|
||||||
|
return environment.getProperty(
|
||||||
|
RadiusGuacamoleProperties.RADIUS_CASE_SENSITIVE_USERNAMES,
|
||||||
|
environment.getCaseSensitiveUsernames()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -205,5 +205,17 @@ public class RadiusGuacamoleProperties {
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A property used to configure whether or not usernames within the RADIUS
|
||||||
|
* module should be treated as case-sensitive.
|
||||||
|
*/
|
||||||
|
public static final BooleanGuacamoleProperty RADIUS_CASE_SENSITIVE_USERNAMES =
|
||||||
|
new BooleanGuacamoleProperty() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() { return "radius-case-sensitive-usernames"; }
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -23,6 +23,8 @@ import com.google.inject.Inject;
|
|||||||
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;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An RADIUS-specific implementation of AuthenticatedUser, associating a
|
* An RADIUS-specific implementation of AuthenticatedUser, associating a
|
||||||
@@ -30,6 +32,11 @@ import org.apache.guacamole.net.auth.Credentials;
|
|||||||
*/
|
*/
|
||||||
public class AuthenticatedUser extends AbstractAuthenticatedUser {
|
public class AuthenticatedUser extends AbstractAuthenticatedUser {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Logger for this class.
|
||||||
|
*/
|
||||||
|
private static final Logger LOGGER = LoggerFactory.getLogger(AuthenticatedUser.class);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reference to the authentication provider associated with this
|
* Reference to the authentication provider associated with this
|
||||||
* authenticated user.
|
* authenticated user.
|
||||||
@@ -37,6 +44,12 @@ public class AuthenticatedUser extends AbstractAuthenticatedUser {
|
|||||||
@Inject
|
@Inject
|
||||||
private AuthenticationProvider authProvider;
|
private AuthenticationProvider authProvider;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A reference to the configuration service associated with this module.
|
||||||
|
*/
|
||||||
|
@Inject
|
||||||
|
private ConfigurationService confService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The credentials provided when this user was authenticated.
|
* The credentials provided when this user was authenticated.
|
||||||
*/
|
*/
|
||||||
@@ -63,4 +76,17 @@ public class AuthenticatedUser extends AbstractAuthenticatedUser {
|
|||||||
return credentials;
|
return credentials;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isCaseSensitive() {
|
||||||
|
try {
|
||||||
|
return confService.getCaseSensitiveUsernames();
|
||||||
|
}
|
||||||
|
catch (GuacamoleException e) {
|
||||||
|
LOGGER.error("Error retrieving configuration for username case sensiivity. "
|
||||||
|
+ "Usernames will be processed as case-sensitive.");
|
||||||
|
LOGGER.debug("Exception caught while retrieving RADIUS configuration.", e);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -23,9 +23,13 @@ import com.google.inject.Inject;
|
|||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import org.apache.guacamole.GuacamoleException;
|
||||||
|
import org.apache.guacamole.environment.Environment;
|
||||||
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;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An AuthenticatedUser whose identity has been supplied by an arbitrary SSO
|
* An AuthenticatedUser whose identity has been supplied by an arbitrary SSO
|
||||||
@@ -35,6 +39,11 @@ import org.apache.guacamole.net.auth.Credentials;
|
|||||||
*/
|
*/
|
||||||
public class SSOAuthenticatedUser extends AbstractAuthenticatedUser {
|
public class SSOAuthenticatedUser extends AbstractAuthenticatedUser {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Logger for this class.
|
||||||
|
*/
|
||||||
|
private static final Logger LOGGER = LoggerFactory.getLogger(SSOAuthenticatedUser.class);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reference to the authentication provider associated with this
|
* Reference to the authentication provider associated with this
|
||||||
* authenticated user.
|
* authenticated user.
|
||||||
@@ -42,6 +51,12 @@ public class SSOAuthenticatedUser extends AbstractAuthenticatedUser {
|
|||||||
@Inject
|
@Inject
|
||||||
private AuthenticationProvider authProvider;
|
private AuthenticationProvider authProvider;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The environment in which this instance of Guacamole is running.
|
||||||
|
*/
|
||||||
|
@Inject
|
||||||
|
private Environment environment;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The credentials provided when this user was authenticated.
|
* The credentials provided when this user was authenticated.
|
||||||
*/
|
*/
|
||||||
@@ -113,4 +128,21 @@ public class SSOAuthenticatedUser extends AbstractAuthenticatedUser {
|
|||||||
return effectiveGroups;
|
return effectiveGroups;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isCaseSensitive() {
|
||||||
|
try {
|
||||||
|
return environment.getCaseSensitiveUsernames();
|
||||||
|
}
|
||||||
|
catch (GuacamoleException e) {
|
||||||
|
// Most SSO systems do not consider usernames to be case-sensitive;
|
||||||
|
// however, in order to avoid any surprises created by the introduction
|
||||||
|
// of case-sensitivity, we've opted to continue to evaluate these
|
||||||
|
// usernames in a case-sensitive manner by default.
|
||||||
|
LOGGER.error("Error occurred when trying to retrieve case-sensitivity configuration: {}. "
|
||||||
|
+ "Usernames comparisons will be done in a case-sensitive manner.", e.getMessage());
|
||||||
|
LOGGER.debug("Exception caught when trying to access the case-sensitivity property.", e);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -20,18 +20,28 @@
|
|||||||
package org.apache.guacamole.auth.cas;
|
package org.apache.guacamole.auth.cas;
|
||||||
|
|
||||||
import com.google.inject.AbstractModule;
|
import com.google.inject.AbstractModule;
|
||||||
|
import org.apache.guacamole.auth.cas.conf.CASEnvironment;
|
||||||
import org.apache.guacamole.auth.cas.conf.ConfigurationService;
|
import org.apache.guacamole.auth.cas.conf.ConfigurationService;
|
||||||
import org.apache.guacamole.auth.cas.ticket.TicketValidationService;
|
import org.apache.guacamole.auth.cas.ticket.TicketValidationService;
|
||||||
|
import org.apache.guacamole.environment.Environment;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Guice module which configures CAS-specific injections.
|
* Guice module which configures CAS-specific injections.
|
||||||
*/
|
*/
|
||||||
public class CASAuthenticationProviderModule extends AbstractModule {
|
public class CASAuthenticationProviderModule extends AbstractModule {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The configuration environment for this server and extension.
|
||||||
|
*/
|
||||||
|
private final Environment environment = new CASEnvironment();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void configure() {
|
protected void configure() {
|
||||||
bind(ConfigurationService.class);
|
bind(ConfigurationService.class);
|
||||||
bind(TicketValidationService.class);
|
bind(TicketValidationService.class);
|
||||||
|
|
||||||
|
bind(Environment.class).toInstance(environment);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -0,0 +1,53 @@
|
|||||||
|
/*
|
||||||
|
* 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.cas.conf;
|
||||||
|
|
||||||
|
import org.apache.guacamole.GuacamoleException;
|
||||||
|
import org.apache.guacamole.environment.DelegatingEnvironment;
|
||||||
|
import org.apache.guacamole.environment.LocalEnvironment;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An environment for retrieving CAS-related properties from the Guacamole
|
||||||
|
* configuration.
|
||||||
|
*/
|
||||||
|
public class CASEnvironment extends DelegatingEnvironment {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new instance of the configuration environment for the
|
||||||
|
* CAS SSO module, pulling the default instance of the LocalEnvironment.
|
||||||
|
*/
|
||||||
|
public CASEnvironment() {
|
||||||
|
super(LocalEnvironment.getInstance());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean getCaseSensitiveUsernames() throws GuacamoleException {
|
||||||
|
|
||||||
|
// While most SSO systems do not consider usernames case-sensitive,
|
||||||
|
// this defaults to the global Guacamole configuration, which defaults
|
||||||
|
// to true, in order to avoid surprising or breaking environments that
|
||||||
|
// may rely on this behavior. This can be overridden for the entire
|
||||||
|
// Guacamole instance or for this extension.
|
||||||
|
return getProperty(CASGuacamoleProperties.CAS_CASE_SENSITIVE_USERNAMES,
|
||||||
|
super.getCaseSensitiveUsernames());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -20,6 +20,7 @@
|
|||||||
package org.apache.guacamole.auth.cas.conf;
|
package org.apache.guacamole.auth.cas.conf;
|
||||||
|
|
||||||
import org.apache.guacamole.auth.cas.group.GroupFormat;
|
import org.apache.guacamole.auth.cas.group.GroupFormat;
|
||||||
|
import org.apache.guacamole.properties.BooleanGuacamoleProperty;
|
||||||
import org.apache.guacamole.properties.EnumGuacamoleProperty;
|
import org.apache.guacamole.properties.EnumGuacamoleProperty;
|
||||||
import org.apache.guacamole.properties.URIGuacamoleProperty;
|
import org.apache.guacamole.properties.URIGuacamoleProperty;
|
||||||
import org.apache.guacamole.properties.StringGuacamoleProperty;
|
import org.apache.guacamole.properties.StringGuacamoleProperty;
|
||||||
@@ -118,4 +119,16 @@ public class CASGuacamoleProperties {
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A property used to configure whether or not usernames within the CAS SSO
|
||||||
|
* module should be treated as case-sensitive.
|
||||||
|
*/
|
||||||
|
public static final BooleanGuacamoleProperty CAS_CASE_SENSITIVE_USERNAMES =
|
||||||
|
new BooleanGuacamoleProperty() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() { return "cas-case-sensitive-usernames"; }
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -22,19 +22,28 @@ package org.apache.guacamole.auth.openid;
|
|||||||
import com.google.inject.AbstractModule;
|
import com.google.inject.AbstractModule;
|
||||||
import com.google.inject.Scopes;
|
import com.google.inject.Scopes;
|
||||||
import org.apache.guacamole.auth.openid.conf.ConfigurationService;
|
import org.apache.guacamole.auth.openid.conf.ConfigurationService;
|
||||||
|
import org.apache.guacamole.auth.openid.conf.OpenIDEnvironment;
|
||||||
import org.apache.guacamole.auth.sso.NonceService;
|
import org.apache.guacamole.auth.sso.NonceService;
|
||||||
import org.apache.guacamole.auth.openid.token.TokenValidationService;
|
import org.apache.guacamole.auth.openid.token.TokenValidationService;
|
||||||
|
import org.apache.guacamole.environment.Environment;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Guice module which configures OpenID-specific injections.
|
* Guice module which configures OpenID-specific injections.
|
||||||
*/
|
*/
|
||||||
public class OpenIDAuthenticationProviderModule extends AbstractModule {
|
public class OpenIDAuthenticationProviderModule extends AbstractModule {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The configuration environment for this server and extension.
|
||||||
|
*/
|
||||||
|
private final Environment environment = new OpenIDEnvironment();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void configure() {
|
protected void configure() {
|
||||||
bind(ConfigurationService.class);
|
bind(ConfigurationService.class);
|
||||||
bind(NonceService.class).in(Scopes.SINGLETON);
|
bind(NonceService.class).in(Scopes.SINGLETON);
|
||||||
bind(TokenValidationService.class);
|
bind(TokenValidationService.class);
|
||||||
|
|
||||||
|
bind(Environment.class).toInstance(environment);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -26,6 +26,7 @@ import java.util.Collections;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import org.apache.guacamole.GuacamoleException;
|
import org.apache.guacamole.GuacamoleException;
|
||||||
import org.apache.guacamole.environment.Environment;
|
import org.apache.guacamole.environment.Environment;
|
||||||
|
import org.apache.guacamole.properties.BooleanGuacamoleProperty;
|
||||||
import org.apache.guacamole.properties.IntegerGuacamoleProperty;
|
import org.apache.guacamole.properties.IntegerGuacamoleProperty;
|
||||||
import org.apache.guacamole.properties.StringGuacamoleProperty;
|
import org.apache.guacamole.properties.StringGuacamoleProperty;
|
||||||
import org.apache.guacamole.properties.URIGuacamoleProperty;
|
import org.apache.guacamole.properties.URIGuacamoleProperty;
|
||||||
@@ -220,6 +221,18 @@ public class ConfigurationService {
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A property used to configure whether or not usernames within the OpenID
|
||||||
|
* SSO module should be treated as case-sensitive.
|
||||||
|
*/
|
||||||
|
public static final BooleanGuacamoleProperty OPENID_CASE_SENSITIVE_USERNAMES =
|
||||||
|
new BooleanGuacamoleProperty() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() { return "openid-case-sensitive-usernames"; }
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The Guacamole server environment.
|
* The Guacamole server environment.
|
||||||
*/
|
*/
|
||||||
|
@@ -0,0 +1,53 @@
|
|||||||
|
/*
|
||||||
|
* 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.openid.conf;
|
||||||
|
|
||||||
|
import org.apache.guacamole.GuacamoleException;
|
||||||
|
import org.apache.guacamole.environment.DelegatingEnvironment;
|
||||||
|
import org.apache.guacamole.environment.LocalEnvironment;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An environment for retrieving OpenID-related properties from the Guacamole
|
||||||
|
* configuration.
|
||||||
|
*/
|
||||||
|
public class OpenIDEnvironment extends DelegatingEnvironment {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new instance of the configuration environment for the
|
||||||
|
* OpenID SSO module, pulling the default instance of the LocalEnvironment.
|
||||||
|
*/
|
||||||
|
public OpenIDEnvironment() {
|
||||||
|
super(LocalEnvironment.getInstance());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean getCaseSensitiveUsernames() throws GuacamoleException {
|
||||||
|
|
||||||
|
// While most SSO systems do not consider usernames case-sensitive,
|
||||||
|
// this defaults to the global Guacamole configuration, which defaults
|
||||||
|
// to true, in order to avoid surprising or breaking environments that
|
||||||
|
// may rely on this behavior. This can be overridden for the entire
|
||||||
|
// Guacamole instance or for this extension.
|
||||||
|
return getProperty(ConfigurationService.OPENID_CASE_SENSITIVE_USERNAMES,
|
||||||
|
super.getCaseSensitiveUsernames());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -24,12 +24,19 @@ import org.apache.guacamole.auth.saml.conf.ConfigurationService;
|
|||||||
import org.apache.guacamole.auth.saml.acs.AssertionConsumerServiceResource;
|
import org.apache.guacamole.auth.saml.acs.AssertionConsumerServiceResource;
|
||||||
import org.apache.guacamole.auth.saml.acs.SAMLAuthenticationSessionManager;
|
import org.apache.guacamole.auth.saml.acs.SAMLAuthenticationSessionManager;
|
||||||
import org.apache.guacamole.auth.saml.acs.SAMLService;
|
import org.apache.guacamole.auth.saml.acs.SAMLService;
|
||||||
|
import org.apache.guacamole.auth.saml.conf.SAMLEnvironment;
|
||||||
|
import org.apache.guacamole.environment.Environment;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Guice module which configures SAML-specific injections.
|
* Guice module which configures SAML-specific injections.
|
||||||
*/
|
*/
|
||||||
public class SAMLAuthenticationProviderModule extends AbstractModule {
|
public class SAMLAuthenticationProviderModule extends AbstractModule {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The environment for this server and extension.
|
||||||
|
*/
|
||||||
|
private final Environment environment = new SAMLEnvironment();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void configure() {
|
protected void configure() {
|
||||||
bind(AssertionConsumerServiceResource.class);
|
bind(AssertionConsumerServiceResource.class);
|
||||||
@@ -37,6 +44,8 @@ public class SAMLAuthenticationProviderModule extends AbstractModule {
|
|||||||
bind(SAMLAuthenticationSessionManager.class);
|
bind(SAMLAuthenticationSessionManager.class);
|
||||||
bind(SAMLService.class);
|
bind(SAMLService.class);
|
||||||
|
|
||||||
|
bind(Environment.class).toInstance(environment);
|
||||||
|
|
||||||
requestStaticInjection(SAMLAuthenticationEventListener.class);
|
requestStaticInjection(SAMLAuthenticationEventListener.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -190,6 +190,18 @@ public class ConfigurationService {
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A property used to configure whether or not usernames within the SAML SSO
|
||||||
|
* module should be treated as case-sensitive.
|
||||||
|
*/
|
||||||
|
public static final BooleanGuacamoleProperty SAML_CASE_SENSITIVE_USERNAMES =
|
||||||
|
new BooleanGuacamoleProperty() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() { return "saml-case-sensitive-usernames"; }
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The Guacamole server environment.
|
* The Guacamole server environment.
|
||||||
*/
|
*/
|
||||||
|
@@ -0,0 +1,53 @@
|
|||||||
|
/*
|
||||||
|
* 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.saml.conf;
|
||||||
|
|
||||||
|
import org.apache.guacamole.GuacamoleException;
|
||||||
|
import org.apache.guacamole.environment.DelegatingEnvironment;
|
||||||
|
import org.apache.guacamole.environment.LocalEnvironment;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An environment for retrieving SAML-related properties from the Guacamole
|
||||||
|
* configuration.
|
||||||
|
*/
|
||||||
|
public class SAMLEnvironment extends DelegatingEnvironment {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new instance of the configuration environment for the
|
||||||
|
* SAML SSO module, pulling the default instance of the LocalEnvironment.
|
||||||
|
*/
|
||||||
|
public SAMLEnvironment() {
|
||||||
|
super(LocalEnvironment.getInstance());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean getCaseSensitiveUsernames() throws GuacamoleException {
|
||||||
|
|
||||||
|
// While most SSO systems do not consider usernames case-sensitive,
|
||||||
|
// this defaults to the global Guacamole configuration, which defaults
|
||||||
|
// to true, in order to avoid surprising or breaking environments that
|
||||||
|
// may rely on this behavior. This can be overridden for the entire
|
||||||
|
// Guacamole instance or for this extension.
|
||||||
|
return getProperty(ConfigurationService.SAML_CASE_SENSITIVE_USERNAMES,
|
||||||
|
super.getCaseSensitiveUsernames());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -22,7 +22,9 @@ package org.apache.guacamole.auth.ssl;
|
|||||||
import com.google.inject.AbstractModule;
|
import com.google.inject.AbstractModule;
|
||||||
import com.google.inject.Scopes;
|
import com.google.inject.Scopes;
|
||||||
import org.apache.guacamole.auth.ssl.conf.ConfigurationService;
|
import org.apache.guacamole.auth.ssl.conf.ConfigurationService;
|
||||||
|
import org.apache.guacamole.auth.ssl.conf.SSLEnvironment;
|
||||||
import org.apache.guacamole.auth.sso.NonceService;
|
import org.apache.guacamole.auth.sso.NonceService;
|
||||||
|
import org.apache.guacamole.environment.Environment;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Guice module which configures injections specific to SSO using SSL/TLS
|
* Guice module which configures injections specific to SSO using SSL/TLS
|
||||||
@@ -30,12 +32,19 @@ import org.apache.guacamole.auth.sso.NonceService;
|
|||||||
*/
|
*/
|
||||||
public class SSLAuthenticationProviderModule extends AbstractModule {
|
public class SSLAuthenticationProviderModule extends AbstractModule {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The configuration environment of this server and extension.
|
||||||
|
*/
|
||||||
|
private final Environment environment = new SSLEnvironment();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void configure() {
|
protected void configure() {
|
||||||
bind(ConfigurationService.class);
|
bind(ConfigurationService.class);
|
||||||
bind(NonceService.class).in(Scopes.SINGLETON);
|
bind(NonceService.class).in(Scopes.SINGLETON);
|
||||||
bind(SSLAuthenticationSessionManager.class);
|
bind(SSLAuthenticationSessionManager.class);
|
||||||
|
|
||||||
|
bind(Environment.class).toInstance(environment);
|
||||||
|
|
||||||
requestStaticInjection(SSLAuthenticationEventListener.class);
|
requestStaticInjection(SSLAuthenticationEventListener.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -28,6 +28,7 @@ import javax.ws.rs.core.UriBuilder;
|
|||||||
import org.apache.guacamole.GuacamoleException;
|
import org.apache.guacamole.GuacamoleException;
|
||||||
import org.apache.guacamole.GuacamoleServerException;
|
import org.apache.guacamole.GuacamoleServerException;
|
||||||
import org.apache.guacamole.environment.Environment;
|
import org.apache.guacamole.environment.Environment;
|
||||||
|
import org.apache.guacamole.properties.BooleanGuacamoleProperty;
|
||||||
import org.apache.guacamole.properties.IntegerGuacamoleProperty;
|
import org.apache.guacamole.properties.IntegerGuacamoleProperty;
|
||||||
import org.apache.guacamole.properties.StringGuacamoleProperty;
|
import org.apache.guacamole.properties.StringGuacamoleProperty;
|
||||||
import org.apache.guacamole.properties.URIGuacamoleProperty;
|
import org.apache.guacamole.properties.URIGuacamoleProperty;
|
||||||
@@ -187,6 +188,18 @@ public class ConfigurationService {
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A property used to configure whether or not usernames within the SSL SSO
|
||||||
|
* module should be treated as case-sensitive.
|
||||||
|
*/
|
||||||
|
public static final BooleanGuacamoleProperty SSL_CASE_SENSITIVE_USERNAMES =
|
||||||
|
new BooleanGuacamoleProperty() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() { return "ssl-case-sensitive-usernames"; }
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The Guacamole server environment.
|
* The Guacamole server environment.
|
||||||
*/
|
*/
|
||||||
|
@@ -0,0 +1,53 @@
|
|||||||
|
/*
|
||||||
|
* 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.ssl.conf;
|
||||||
|
|
||||||
|
import org.apache.guacamole.GuacamoleException;
|
||||||
|
import org.apache.guacamole.environment.DelegatingEnvironment;
|
||||||
|
import org.apache.guacamole.environment.LocalEnvironment;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An environment for retrieving SSL-related properties from the Guacamole
|
||||||
|
* configuration.
|
||||||
|
*/
|
||||||
|
public class SSLEnvironment extends DelegatingEnvironment {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new instance of the configuration environment for the
|
||||||
|
* SSL SSO module, pulling the default instance of the LocalEnvironment.
|
||||||
|
*/
|
||||||
|
public SSLEnvironment() {
|
||||||
|
super(LocalEnvironment.getInstance());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean getCaseSensitiveUsernames() throws GuacamoleException {
|
||||||
|
|
||||||
|
// While most SSO systems do not consider usernames case-sensitive,
|
||||||
|
// this defaults to the global Guacamole configuration, which defaults
|
||||||
|
// to true, in order to avoid surprising or breaking environments that
|
||||||
|
// may rely on this behavior. This can be overridden for the entire
|
||||||
|
// Guacamole instance or for this extension.
|
||||||
|
return getProperty(ConfigurationService.SSL_CASE_SENSITIVE_USERNAMES,
|
||||||
|
super.getCaseSensitiveUsernames());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -114,4 +114,9 @@ public class DelegatingEnvironment implements Environment {
|
|||||||
environment.addGuacamoleProperties(properties);
|
environment.addGuacamoleProperties(properties);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean getCaseSensitiveUsernames() throws GuacamoleException {
|
||||||
|
return environment.getCaseSensitiveUsernames();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -70,6 +70,18 @@ public interface Environment {
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A property that configures whether or not Guacamole will take case
|
||||||
|
* into account when comparing and processing usernames.
|
||||||
|
*/
|
||||||
|
public static final BooleanGuacamoleProperty CASE_SENSITIVE_USERNAMES =
|
||||||
|
new BooleanGuacamoleProperty() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() { return "case-sensitive-usernames"; }
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the Guacamole home directory as determined when this Environment
|
* Returns the Guacamole home directory as determined when this Environment
|
||||||
* object was created. The Guacamole home directory is found by checking, in
|
* object was created. The Guacamole home directory is found by checking, in
|
||||||
@@ -368,4 +380,22 @@ public interface Environment {
|
|||||||
getClass()));
|
getClass()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if Guacamole should consider case when comparing and
|
||||||
|
* processing usernames (case-sensitive), or false if case should not be
|
||||||
|
* considered (case-insensitive). Because the past behavior of Guacamole,
|
||||||
|
* prior to the introduction of this option, was case-sensitive, the default
|
||||||
|
* value is true.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* true if Guacamole should consider usernames case-sensitive, otherwise
|
||||||
|
* false.
|
||||||
|
*
|
||||||
|
* @throws GuacamoleException
|
||||||
|
* If guacamole.properties cannot be parsed.
|
||||||
|
*/
|
||||||
|
public default boolean getCaseSensitiveUsernames() throws GuacamoleException {
|
||||||
|
return getProperty(CASE_SENSITIVE_USERNAMES, true);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -19,7 +19,6 @@
|
|||||||
|
|
||||||
package org.apache.guacamole.net.auth;
|
package org.apache.guacamole.net.auth;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Abstract implementation of Identifiable which provides equals() and
|
* Abstract implementation of Identifiable which provides equals() and
|
||||||
* hashCode() implementations which use the identifier to determine equality.
|
* hashCode() implementations which use the identifier to determine equality.
|
||||||
@@ -34,12 +33,18 @@ public abstract class AbstractIdentifiable implements Identifiable {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getIdentifier() {
|
public String getIdentifier() {
|
||||||
return identifier;
|
if (identifier == null || isCaseSensitive())
|
||||||
|
return identifier;
|
||||||
|
|
||||||
|
return identifier.toLowerCase();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setIdentifier(String identifier) {
|
public void setIdentifier(String identifier) {
|
||||||
this.identifier = identifier;
|
if (isCaseSensitive() || identifier == null)
|
||||||
|
this.identifier = identifier;
|
||||||
|
else
|
||||||
|
this.identifier = identifier.toLowerCase();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -48,7 +53,10 @@ public abstract class AbstractIdentifiable implements Identifiable {
|
|||||||
if (identifier == null)
|
if (identifier == null)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
return identifier.hashCode();
|
if (isCaseSensitive())
|
||||||
|
return identifier.hashCode();
|
||||||
|
|
||||||
|
return identifier.toLowerCase().hashCode();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -65,8 +73,12 @@ public abstract class AbstractIdentifiable implements Identifiable {
|
|||||||
if (otherIdentifier == null)
|
if (otherIdentifier == null)
|
||||||
return identifier == null;
|
return identifier == null;
|
||||||
|
|
||||||
// Otherwise, equal only if strings are identical
|
// If this identifier is case-sensitive, evaluate with case-sensitivity.
|
||||||
return otherIdentifier.equals(identifier);
|
if (isCaseSensitive())
|
||||||
|
return otherIdentifier.equals(identifier);
|
||||||
|
|
||||||
|
// The identifier should not be evaluated in a case-sensitive manner.
|
||||||
|
return otherIdentifier.equalsIgnoreCase(identifier);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -50,6 +50,14 @@ public abstract class AbstractUser extends AbstractIdentifiable
|
|||||||
this.password = password;
|
this.password = password;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isCaseSensitive() {
|
||||||
|
|
||||||
|
// In order to avoid causing incompatibility with other extensions,
|
||||||
|
// this class maintains case-sensitive comparisons.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
*
|
*
|
||||||
|
@@ -44,4 +44,17 @@ public interface Identifiable {
|
|||||||
*/
|
*/
|
||||||
public void setIdentifier(String identifier);
|
public void setIdentifier(String identifier);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether or not this identifier should be evaluated in a case-sensitive
|
||||||
|
* manner or not. By default this returns true and the identifier will
|
||||||
|
* be evaluated in a case-sensitive manner.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* True if the comparisons of this identifier should be case-sensitive,
|
||||||
|
* otherwise false.
|
||||||
|
*/
|
||||||
|
default public boolean isCaseSensitive() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user