GUAC-1101: Restrict object manipulation depending on create/update/delete permission.

This commit is contained in:
Michael Jumper
2015-02-12 23:36:51 -08:00
parent 0e38acbd59
commit 7a6af903fb
6 changed files with 108 additions and 15 deletions

View File

@@ -22,6 +22,8 @@
package net.sourceforge.guacamole.net.auth.mysql; package net.sourceforge.guacamole.net.auth.mysql;
import org.glyptodon.guacamole.net.auth.Identifiable;
/** /**
* Common interface for objects that will ultimately be made available through * Common interface for objects that will ultimately be made available through
* the Directory class. All such objects will need the same base set of queries * the Directory class. All such objects will need the same base set of queries
@@ -32,7 +34,7 @@ package net.sourceforge.guacamole.net.auth.mysql;
* The type of object contained within the directory whose objects are * The type of object contained within the directory whose objects are
* mapped by this mapper. * mapped by this mapper.
*/ */
public interface DirectoryObject<ModelType> { public interface DirectoryObject<ModelType> extends Identifiable {
/** /**
* Returns the backing model object. Changes to the model object will * Returns the backing model object. Changes to the model object will

View File

@@ -97,12 +97,12 @@ public class MySQLUser implements User, DirectoryObject<UserModel> {
} }
@Override @Override
public String getUsername() { public String getIdentifier() {
return userModel.getUsername(); return userModel.getUsername();
} }
@Override @Override
public void setUsername(String username) { public void setIdentifier(String username) {
userModel.setUsername(username); userModel.setUsername(username);
} }
@@ -151,24 +151,24 @@ public class MySQLUser implements User, DirectoryObject<UserModel> {
} }
@Override @Override
public ObjectPermissionSet<String> getConnectionPermissions() public ObjectPermissionSet getConnectionPermissions()
throws GuacamoleException { throws GuacamoleException {
// STUB // STUB
return new SimpleObjectPermissionSet<String>(); return new SimpleObjectPermissionSet();
} }
@Override @Override
public ObjectPermissionSet<String> getConnectionGroupPermissions() public ObjectPermissionSet getConnectionGroupPermissions()
throws GuacamoleException { throws GuacamoleException {
// STUB // STUB
return new SimpleObjectPermissionSet<String>(); return new SimpleObjectPermissionSet();
} }
@Override @Override
public ObjectPermissionSet<String> getUserPermissions() public ObjectPermissionSet getUserPermissions()
throws GuacamoleException { throws GuacamoleException {
// STUB // STUB
return new SimpleObjectPermissionSet<String>(); return new SimpleObjectPermissionSet();
} }
} }

View File

@@ -69,7 +69,7 @@ public class MySQLUserContext implements UserContext {
} }
@Override @Override
public Directory<String, User> getUserDirectory() throws GuacamoleException { public Directory<User> getUserDirectory() throws GuacamoleException {
return userDirectory; return userDirectory;
} }

View File

@@ -40,7 +40,7 @@ import org.mybatis.guice.transactional.Transactional;
* @author James Muehlner * @author James Muehlner
* @author Michael Jumper * @author Michael Jumper
*/ */
public class UserDirectory implements Directory<String, User> { public class UserDirectory implements Directory<User> {
/** /**
* The user this user directory belongs to. Access is based on his/her * The user this user directory belongs to. Access is based on his/her
@@ -66,7 +66,7 @@ public class UserDirectory implements Directory<String, User> {
} }
@Override @Override
public void move(String identifier, Directory<String, User> groupIdentifier) public void move(String identifier, Directory<User> groupIdentifier)
throws GuacamoleException { throws GuacamoleException {
throw new GuacamoleSecurityException("Permission denied."); throw new GuacamoleSecurityException("Permission denied.");
} }

View File

@@ -30,6 +30,9 @@ import net.sourceforge.guacamole.net.auth.mysql.AuthenticatedUser;
import net.sourceforge.guacamole.net.auth.mysql.DirectoryObject; import net.sourceforge.guacamole.net.auth.mysql.DirectoryObject;
import net.sourceforge.guacamole.net.auth.mysql.dao.DirectoryObjectMapper; import net.sourceforge.guacamole.net.auth.mysql.dao.DirectoryObjectMapper;
import org.glyptodon.guacamole.GuacamoleException; import org.glyptodon.guacamole.GuacamoleException;
import org.glyptodon.guacamole.GuacamoleSecurityException;
import org.glyptodon.guacamole.net.auth.permission.ObjectPermission;
import org.glyptodon.guacamole.net.auth.permission.ObjectPermissionSet;
/** /**
* Service which provides convenience methods for creating, retrieving, and * Service which provides convenience methods for creating, retrieving, and
@@ -67,6 +70,41 @@ public abstract class DirectoryObjectService<ObjectType extends DirectoryObject<
*/ */
protected abstract ObjectType getObjectInstance(ModelType model); protected abstract ObjectType getObjectInstance(ModelType model);
/**
* Returns whether the given user has permission to create the type of
* objects that this directory object service manages.
*
* @param user
* The user being checked.
*
* @return
* true if the user has object creation permission relevant to this
* directory object service, false otherwise.
*
* @throws GuacamoleException
* If permission to read the user's permissions is denied.
*/
protected abstract boolean hasCreatePermission(AuthenticatedUser user)
throws GuacamoleException;
/**
* Returns the permission set associated with the given user and related
* to the type of objects handled by this directory object service.
*
* @param user
* The user whose permissions are being retrieved.
*
* @return
* A permission set which contains the permissions associated with the
* given user and related to the type of objects handled by this
* directory object service.
*
* @throws GuacamoleException
* If permission to read the user's permissions is denied.
*/
protected abstract ObjectPermissionSet getPermissionSet(AuthenticatedUser user)
throws GuacamoleException;
/** /**
* Returns a collection of objects which are backed by the models in the * Returns a collection of objects which are backed by the models in the
* given collection. * given collection.
@@ -181,7 +219,14 @@ public abstract class DirectoryObjectService<ObjectType extends DirectoryObject<
*/ */
public void createObject(AuthenticatedUser user, ObjectType object) public void createObject(AuthenticatedUser user, ObjectType object)
throws GuacamoleException { throws GuacamoleException {
getObjectMapper().insert(object.getModel());
// Only create object if user has permission to do so
if (user.getUser().isAdministrator() || hasCreatePermission(user))
getObjectMapper().insert(object.getModel());
// User lacks permission to create
throw new GuacamoleSecurityException("Permission denied.");
} }
/** /**
@@ -200,7 +245,18 @@ public abstract class DirectoryObjectService<ObjectType extends DirectoryObject<
*/ */
public void deleteObject(AuthenticatedUser user, String identifier) public void deleteObject(AuthenticatedUser user, String identifier)
throws GuacamoleException { throws GuacamoleException {
getObjectMapper().delete(identifier);
// Get object permissions
ObjectPermissionSet permissionSet = getPermissionSet(user);
// Only delete object if user has permission to do so
if (user.getUser().isAdministrator()
|| permissionSet.hasPermission(ObjectPermission.Type.DELETE, identifier))
getObjectMapper().delete(identifier);
// User lacks permission to delete
throw new GuacamoleSecurityException("Permission denied.");
} }
/** /**
@@ -219,7 +275,18 @@ public abstract class DirectoryObjectService<ObjectType extends DirectoryObject<
*/ */
public void updateObject(AuthenticatedUser user, ObjectType object) public void updateObject(AuthenticatedUser user, ObjectType object)
throws GuacamoleException { throws GuacamoleException {
getObjectMapper().update(object.getModel());
// Get object permissions
ObjectPermissionSet permissionSet = getPermissionSet(user);
// Only update object if user has permission to do so
if (user.getUser().isAdministrator()
|| permissionSet.hasPermission(ObjectPermission.Type.UPDATE, object.getIdentifier()))
getObjectMapper().update(object.getModel());
// User lacks permission to update
throw new GuacamoleSecurityException("Permission denied.");
} }
/** /**

View File

@@ -24,11 +24,16 @@ package net.sourceforge.guacamole.net.auth.mysql.service;
import com.google.inject.Inject; import com.google.inject.Inject;
import com.google.inject.Provider; import com.google.inject.Provider;
import net.sourceforge.guacamole.net.auth.mysql.AuthenticatedUser;
import org.glyptodon.guacamole.net.auth.Credentials; import org.glyptodon.guacamole.net.auth.Credentials;
import net.sourceforge.guacamole.net.auth.mysql.MySQLUser; import net.sourceforge.guacamole.net.auth.mysql.MySQLUser;
import net.sourceforge.guacamole.net.auth.mysql.dao.DirectoryObjectMapper; import net.sourceforge.guacamole.net.auth.mysql.dao.DirectoryObjectMapper;
import net.sourceforge.guacamole.net.auth.mysql.dao.UserMapper; import net.sourceforge.guacamole.net.auth.mysql.dao.UserMapper;
import net.sourceforge.guacamole.net.auth.mysql.model.UserModel; import net.sourceforge.guacamole.net.auth.mysql.model.UserModel;
import org.glyptodon.guacamole.GuacamoleException;
import org.glyptodon.guacamole.net.auth.permission.ObjectPermissionSet;
import org.glyptodon.guacamole.net.auth.permission.SystemPermission;
import org.glyptodon.guacamole.net.auth.permission.SystemPermissionSet;
/** /**
* Service which provides convenience methods for creating, retrieving, and * Service which provides convenience methods for creating, retrieving, and
@@ -62,6 +67,25 @@ public class UserService extends DirectoryObjectService<MySQLUser, UserModel> {
return user; return user;
} }
@Override
protected boolean hasCreatePermission(AuthenticatedUser user)
throws GuacamoleException {
// Return whether user has explicit user creation permission
SystemPermissionSet permissionSet = user.getUser().getSystemPermissions();
return permissionSet.hasPermission(SystemPermission.Type.CREATE_USER);
}
@Override
protected ObjectPermissionSet getPermissionSet(AuthenticatedUser user)
throws GuacamoleException {
// Return permissions related to users
return user.getUser().getUserPermissions();
}
/** /**
* Retrieves the user corresponding to the given credentials from the * Retrieves the user corresponding to the given credentials from the
* database. * database.