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;
import org.glyptodon.guacamole.net.auth.Identifiable;
/**
* 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
@@ -32,7 +34,7 @@ package net.sourceforge.guacamole.net.auth.mysql;
* The type of object contained within the directory whose objects are
* 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

View File

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

View File

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

View File

@@ -40,7 +40,7 @@ import org.mybatis.guice.transactional.Transactional;
* @author James Muehlner
* @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
@@ -66,7 +66,7 @@ public class UserDirectory implements Directory<String, User> {
}
@Override
public void move(String identifier, Directory<String, User> groupIdentifier)
public void move(String identifier, Directory<User> groupIdentifier)
throws GuacamoleException {
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.dao.DirectoryObjectMapper;
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
@@ -67,6 +70,41 @@ public abstract class DirectoryObjectService<ObjectType extends DirectoryObject<
*/
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
* given collection.
@@ -181,7 +219,14 @@ public abstract class DirectoryObjectService<ObjectType extends DirectoryObject<
*/
public void createObject(AuthenticatedUser user, ObjectType object)
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)
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)
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.Provider;
import net.sourceforge.guacamole.net.auth.mysql.AuthenticatedUser;
import org.glyptodon.guacamole.net.auth.Credentials;
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.UserMapper;
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
@@ -62,6 +67,25 @@ public class UserService extends DirectoryObjectService<MySQLUser, UserModel> {
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
* database.