From 8d6790f1830e54897eabd33a21e5571cda8744a4 Mon Sep 17 00:00:00 2001 From: Virtually Nick Date: Sat, 28 Sep 2024 19:39:59 -0400 Subject: [PATCH] GUACAMOLE-1020: Make sure only admin users can modify restrictions. --- .../auth/restrict/user/RestrictedUser.java | 21 +++++++++++++--- .../restrict/user/RestrictedUserContext.java | 24 ++++++++++++++++--- 2 files changed, 39 insertions(+), 6 deletions(-) diff --git a/extensions/guacamole-auth-restrict/src/main/java/org/apache/guacamole/auth/restrict/user/RestrictedUser.java b/extensions/guacamole-auth-restrict/src/main/java/org/apache/guacamole/auth/restrict/user/RestrictedUser.java index 84e2bac500..c66032e611 100644 --- a/extensions/guacamole-auth-restrict/src/main/java/org/apache/guacamole/auth/restrict/user/RestrictedUser.java +++ b/extensions/guacamole-auth-restrict/src/main/java/org/apache/guacamole/auth/restrict/user/RestrictedUser.java @@ -43,6 +43,12 @@ public class RestrictedUser extends DelegatingUser implements Restrictable { */ private final String remoteAddress; + /** + * true if the user logged in to Guacamole has administrative privileges + * for this user object, otherwise false. + */ + private final boolean hasAdmin; + /** * The name of the attribute that contains a list of weekdays and times (UTC) * that a user is allowed to log in. The presence of this attribute will @@ -116,9 +122,10 @@ public class RestrictedUser extends DelegatingUser implements Restrictable { * The remote address of the client from which the current user is logged * in. */ - public RestrictedUser(User user, String remoteAddress) { + public RestrictedUser(User user, String remoteAddress, boolean hasAdmin) { super(user); this.remoteAddress = remoteAddress; + this.hasAdmin = hasAdmin; } /** @@ -133,7 +140,7 @@ public User getUndecorated() { @Override public Map getAttributes() { - + // Create independent, mutable copy of attributes Map attributes = new HashMap<>(super.getAttributes()); @@ -154,10 +161,18 @@ public void setAttributes(Map attributes) { // Create independent, mutable copy of attributes attributes = new HashMap<>(attributes); - + // Loop through extension-specific attributes, only sending ones // that are non-null and non-empty to the underlying storage mechanism. for (String attribute : RESTRICT_USER_ATTRIBUTES) { + + /* If the user lacks admin access, don't set restriction attributes. */ + if (!hasAdmin) { + attributes.remove(attribute); + continue; + } + + /* Replace empty values with null values. */ String value = attributes.get(attribute); if (value != null && value.isEmpty()) attributes.put(attribute, null); diff --git a/extensions/guacamole-auth-restrict/src/main/java/org/apache/guacamole/auth/restrict/user/RestrictedUserContext.java b/extensions/guacamole-auth-restrict/src/main/java/org/apache/guacamole/auth/restrict/user/RestrictedUserContext.java index 943e08b072..5fa1963b0a 100644 --- a/extensions/guacamole-auth-restrict/src/main/java/org/apache/guacamole/auth/restrict/user/RestrictedUserContext.java +++ b/extensions/guacamole-auth-restrict/src/main/java/org/apache/guacamole/auth/restrict/user/RestrictedUserContext.java @@ -34,9 +34,12 @@ import org.apache.guacamole.net.auth.DecoratingDirectory; import org.apache.guacamole.net.auth.DelegatingUserContext; import org.apache.guacamole.net.auth.Directory; +import org.apache.guacamole.net.auth.Permissions; import org.apache.guacamole.net.auth.User; import org.apache.guacamole.net.auth.UserContext; import org.apache.guacamole.net.auth.UserGroup; +import org.apache.guacamole.net.auth.permission.ObjectPermission; +import org.apache.guacamole.net.auth.permission.SystemPermission; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -60,7 +63,7 @@ public class RestrictedUserContext extends DelegatingUserContext { * The identifiers effective groups of the user associated with this context. */ private final Set effectiveUserGroups; - + /** * Creates a new RestrictedUserContext which wraps the given UserContext, * providing additional control for user logins and connections. @@ -133,11 +136,26 @@ public Collection
getConnectionGroupAttributes() { @Override public Directory getUserDirectory() throws GuacamoleException { + + // Pull permissions of the current logged-in user. + Permissions currentPermissions = self().getEffectivePermissions(); + return new DecoratingDirectory(super.getUserDirectory()) { @Override - protected User decorate(User object) { - return new RestrictedUser(object, remoteAddress); + protected User decorate(User object) throws GuacamoleException { + + // Check and see if the logged in user has admin privileges - + // either system-level or for that particular object. + boolean hasAdmin = + currentPermissions.getSystemPermissions().hasPermission( + SystemPermission.Type.ADMINISTER + ) + || currentPermissions.getUserPermissions().hasPermission( + ObjectPermission.Type.ADMINISTER, + object.getIdentifier() + ); + return new RestrictedUser(object, remoteAddress, hasAdmin); } @Override