mirror of
https://github.com/gyurix1968/guacamole-client.git
synced 2025-09-06 13:17:41 +00:00
GUAC-1101: Limit results of retrieval operations by read permissions, unless user is a sysadmin.
This commit is contained in:
@@ -29,6 +29,7 @@ import net.sourceforge.guacamole.net.auth.mysql.service.SaltService;
|
||||
import org.glyptodon.guacamole.GuacamoleException;
|
||||
import org.glyptodon.guacamole.net.auth.User;
|
||||
import org.glyptodon.guacamole.net.auth.permission.ObjectPermissionSet;
|
||||
import org.glyptodon.guacamole.net.auth.permission.SystemPermission;
|
||||
import org.glyptodon.guacamole.net.auth.permission.SystemPermissionSet;
|
||||
import org.glyptodon.guacamole.net.auth.simple.SimpleObjectPermissionSet;
|
||||
import org.glyptodon.guacamole.net.auth.simple.SimpleSystemPermissionSet;
|
||||
@@ -126,6 +127,22 @@ public class MySQLUser implements User, DirectoryObject<UserModel> {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether this user is a system administrator, and thus is not
|
||||
* restricted by permissions.
|
||||
*
|
||||
* @return
|
||||
* true if this user is a system administrator, false otherwise.
|
||||
*
|
||||
* @throws GuacamoleException
|
||||
* If an error occurs while determining the user's system administrator
|
||||
* status.
|
||||
*/
|
||||
public boolean isAdministrator() throws GuacamoleException {
|
||||
SystemPermissionSet systemPermissionSet = getSystemPermissions();
|
||||
return systemPermissionSet.hasPermission(SystemPermission.Type.ADMINISTER);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SystemPermissionSet getSystemPermissions()
|
||||
throws GuacamoleException {
|
||||
|
@@ -24,6 +24,7 @@ package net.sourceforge.guacamole.net.auth.mysql.dao;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Set;
|
||||
import net.sourceforge.guacamole.net.auth.mysql.model.UserModel;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
/**
|
||||
@@ -32,23 +33,45 @@ import org.apache.ibatis.annotations.Param;
|
||||
* to fulfill the needs of the Directory class.
|
||||
*
|
||||
* @author Michael Jumper
|
||||
* @param <T>
|
||||
* @param <ModelType>
|
||||
* The type of object contained within the directory whose objects are
|
||||
* mapped by this mapper.
|
||||
*/
|
||||
public interface DirectoryObjectMapper<T> {
|
||||
public interface DirectoryObjectMapper<ModelType> {
|
||||
|
||||
/**
|
||||
* Selects the identifiers of all objects.
|
||||
* Selects the identifiers of all objects, regardless of whether they
|
||||
* are readable by any particular user. This should only be called on
|
||||
* behalf of a system administrator. If identifiers are needed by a non-
|
||||
* administrative user who must have explicit read rights, use
|
||||
* selectReadableIdentifiers() instead.
|
||||
*
|
||||
* @return
|
||||
* A Set containing all identifiers of all objects.
|
||||
*/
|
||||
Set<String> selectIdentifiers();
|
||||
|
||||
/**
|
||||
* Selects the identifiers of all objects that are explicitly readable by
|
||||
* the given user. If identifiers are needed by a system administrator
|
||||
* (who, by definition, does not need explicit read rights), use
|
||||
* selectIdentifiers() instead.
|
||||
*
|
||||
* @param user
|
||||
* The user whose permissions should determine whether an identifier
|
||||
* is returned.
|
||||
*
|
||||
* @return
|
||||
* A Set containing all identifiers of all readable objects.
|
||||
*/
|
||||
Set<String> selectReadableIdentifiers(@Param("user") UserModel user);
|
||||
|
||||
/**
|
||||
* Selects all objects which have the given identifiers. If an identifier
|
||||
* has no corresponding object, it will be ignored.
|
||||
* has no corresponding object, it will be ignored. This should only be
|
||||
* called on behalf of a system administrator. If objects are needed by a
|
||||
* non-administrative user who must have explicit read rights, use
|
||||
* selectReadable() instead.
|
||||
*
|
||||
* @param identifiers
|
||||
* The identifiers of the objects to return.
|
||||
@@ -56,7 +79,27 @@ public interface DirectoryObjectMapper<T> {
|
||||
* @return
|
||||
* A Collection of all objects having the given identifiers.
|
||||
*/
|
||||
Collection<T> select(@Param("identifiers") Collection<String> identifiers);
|
||||
Collection<ModelType> select(@Param("identifiers") Collection<String> identifiers);
|
||||
|
||||
/**
|
||||
* Selects all objects which have the given identifiers and are explicitly
|
||||
* readably by the given user. If an identifier has no corresponding
|
||||
* object, or the corresponding object is unreadable, it will be ignored.
|
||||
* If objects 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 objects to return.
|
||||
*
|
||||
* @return
|
||||
* A Collection of all objects having the given identifiers.
|
||||
*/
|
||||
Collection<ModelType> selectReadable(@Param("user") UserModel user,
|
||||
@Param("identifiers") Collection<String> identifiers);
|
||||
|
||||
/**
|
||||
* Inserts the given object into the database. If the object already
|
||||
@@ -68,7 +111,7 @@ public interface DirectoryObjectMapper<T> {
|
||||
* @return
|
||||
* The number of rows inserted.
|
||||
*/
|
||||
int insert(@Param("object") T object);
|
||||
int insert(@Param("object") ModelType object);
|
||||
|
||||
/**
|
||||
* Deletes the given object into the database. If the object does not
|
||||
@@ -92,6 +135,6 @@ public interface DirectoryObjectMapper<T> {
|
||||
* @return
|
||||
* The number of rows updated.
|
||||
*/
|
||||
int update(@Param("object") T object);
|
||||
int update(@Param("object") ModelType object);
|
||||
|
||||
}
|
@@ -103,9 +103,12 @@ public abstract class DirectoryObjectService<ObjectType extends DirectoryObject<
|
||||
* @return
|
||||
* The object having the given identifier, or null if no such object
|
||||
* exists.
|
||||
*
|
||||
* @throws GuacamoleException
|
||||
* If an error occurs while retrieving the requested object.
|
||||
*/
|
||||
public ObjectType retrieveObject(AuthenticatedUser user,
|
||||
String identifier) {
|
||||
String identifier) throws GuacamoleException {
|
||||
|
||||
// Pull objects having given identifier
|
||||
Collection<ObjectType> objects = retrieveObjects(user, Collections.singleton(identifier));
|
||||
@@ -135,16 +138,29 @@ public abstract class DirectoryObjectService<ObjectType extends DirectoryObject<
|
||||
*
|
||||
* @return
|
||||
* The objects having the given identifiers.
|
||||
*
|
||||
* @throws GuacamoleException
|
||||
* If an error occurs while retrieving the requested objects.
|
||||
*/
|
||||
public Collection<ObjectType> retrieveObjects(AuthenticatedUser user,
|
||||
Collection<String> identifiers) {
|
||||
Collection<String> identifiers) throws GuacamoleException {
|
||||
|
||||
// Do not query if no identifiers given
|
||||
if (identifiers.isEmpty())
|
||||
return Collections.EMPTY_LIST;
|
||||
|
||||
Collection<ModelType> objects;
|
||||
|
||||
// Bypass permission checks if the user is a system admin
|
||||
if (user.getUser().isAdministrator())
|
||||
objects = getObjectMapper().select(identifiers);
|
||||
|
||||
// Otherwise only return explicitly readable identifiers
|
||||
else
|
||||
objects = getObjectMapper().selectReadable(user.getUser().getModel(), identifiers);
|
||||
|
||||
// Return collection of requested objects
|
||||
return getObjectInstances(getObjectMapper().select(identifiers));
|
||||
return getObjectInstances(objects);
|
||||
|
||||
}
|
||||
|
||||
@@ -215,9 +231,21 @@ public abstract class DirectoryObjectService<ObjectType extends DirectoryObject<
|
||||
*
|
||||
* @return
|
||||
* The set of all identifiers for all objects in the database.
|
||||
*
|
||||
* @throws GuacamoleException
|
||||
* If an error occurs while reading identifiers.
|
||||
*/
|
||||
public Set<String> getIdentifiers(AuthenticatedUser user) {
|
||||
return getObjectMapper().selectIdentifiers();
|
||||
public Set<String> getIdentifiers(AuthenticatedUser user)
|
||||
throws GuacamoleException {
|
||||
|
||||
// Bypass permission checks if the user is a system admin
|
||||
if (user.getUser().isAdministrator())
|
||||
return getObjectMapper().selectIdentifiers();
|
||||
|
||||
// Otherwise only return explicitly readable identifiers
|
||||
else
|
||||
return getObjectMapper().selectReadableIdentifiers(user.getUser().getModel());
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -40,6 +40,16 @@
|
||||
FROM guacamole_user
|
||||
</select>
|
||||
|
||||
<!-- Select usernames of all readable users -->
|
||||
<select id="selectReadableIdentifiers" resultType="string">
|
||||
SELECT username
|
||||
FROM guacamole_user
|
||||
JOIN guacamole_user_permission ON affected_user_id = guacamole_user.user_id
|
||||
WHERE
|
||||
guacamole_user_permission.user_id = #{user.userID,jdbcType=INTEGER}
|
||||
AND permission = 'read'
|
||||
</select>
|
||||
|
||||
<!-- Select multiple users by username -->
|
||||
<select id="select" resultMap="UserResultMap">
|
||||
|
||||
@@ -57,6 +67,27 @@
|
||||
|
||||
</select>
|
||||
|
||||
<!-- Select multiple users by username only if readable -->
|
||||
<select id="selectReadable" resultMap="UserResultMap">
|
||||
|
||||
SELECT
|
||||
guacamole_user.user_id,
|
||||
username,
|
||||
password_hash,
|
||||
password_salt
|
||||
FROM guacamole_user
|
||||
JOIN guacamole_user_permission ON affected_user_id = guacamole_user.user_id
|
||||
WHERE username IN
|
||||
<foreach collection="identifiers" item="identifier"
|
||||
open="(" separator="," close=")">
|
||||
#{identifier,jdbcType=VARCHAR}
|
||||
</foreach>
|
||||
AND guacamole_user_permission.user_id = #{user.userID,jdbcType=INTEGER}
|
||||
AND permission = 'read'
|
||||
|
||||
</select>
|
||||
|
||||
|
||||
<select id="selectByCredentials" resultMap="UserResultMap">
|
||||
SELECT
|
||||
user_id,
|
||||
|
Reference in New Issue
Block a user