diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/JDBCAuthenticationProviderService.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/JDBCAuthenticationProviderService.java index 1bb2c68e7..3f54be811 100644 --- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/JDBCAuthenticationProviderService.java +++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/JDBCAuthenticationProviderService.java @@ -27,6 +27,7 @@ import org.apache.guacamole.auth.jdbc.sharing.user.SharedAuthenticatedUser; import org.apache.guacamole.auth.jdbc.user.ModeledAuthenticatedUser; import org.apache.guacamole.auth.jdbc.user.ModeledUser; import org.apache.guacamole.auth.jdbc.user.ModeledUserContext; +import org.apache.guacamole.auth.jdbc.user.PrivilegedModeledAuthenticatedUser; import org.apache.guacamole.auth.jdbc.user.UserService; import org.apache.guacamole.language.TranslatableGuacamoleClientException; import org.apache.guacamole.net.auth.AuthenticatedUser; @@ -98,7 +99,7 @@ public class JDBCAuthenticationProviderService implements AuthenticationProvider ModeledUser user = userService.retrieveUser(authenticationProvider, authenticatedUser); ModeledUserContext context = userContextProvider.get(); if (user != null && !user.isDisabled()) { - + // Enforce applicable account restrictions if (databaseRestrictionsApplicable) { @@ -126,9 +127,15 @@ public class JDBCAuthenticationProviderService implements AuthenticationProvider } // If no user account is found, and database-specific account - // restrictions do not apply, get an empty user. + // restrictions do not apply, get a skeleton user. else if (!databaseRestrictionsApplicable) { user = userService.retrieveSkeletonUser(authenticationProvider, authenticatedUser); + + // If auto account creation is enabled, add user to DB. + if (environment.autoCreateAbsentAccounts()) { + userService.createObject(new PrivilegedModeledAuthenticatedUser(user.getCurrentUser()), user); + } + } // Veto authentication result only if database-specific account diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/JDBCEnvironment.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/JDBCEnvironment.java index 9158afb85..7c9a4b113 100644 --- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/JDBCEnvironment.java +++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/JDBCEnvironment.java @@ -151,5 +151,21 @@ public abstract class JDBCEnvironment extends LocalEnvironment { * true if the database supports recursive queries, false otherwise. */ public abstract boolean isRecursiveQuerySupported(SqlSession session); + + /** + * Returns a boolean value representing whether or not the JDBC module + * should automatically create accounts within the database for users that + * are successfully authenticated via other extensions. Returns true if + * accounts should be auto-created, otherwise returns false. + * + * @return + * true if user accounts should be automatically created within the + * database when authentication succeeds from another extension; + * otherwise false. + * + * @throws GuacamoleException + * If guacamole.properties cannot be parsed. + */ + public abstract boolean autoCreateAbsentAccounts() throws GuacamoleException; } diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/base/ModeledDirectoryObjectService.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/base/ModeledDirectoryObjectService.java index f8d0e8a8a..133e6628c 100644 --- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/base/ModeledDirectoryObjectService.java +++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/base/ModeledDirectoryObjectService.java @@ -410,9 +410,9 @@ public abstract class ModeledDirectoryObjectService getImplicitPermissions(ModeledAuthenticatedUser user, ModelType model) { + // Check to see if the user granting permissions is a skeleton user, + // thus lacking database backing. + if (user.getUser().isSkeleton()) + return Collections.emptyList(); + + // Get the user model and check for an entity ID. + UserModel userModel = user.getUser().getModel(); + // Build list of implicit permissions Collection implicitPermissions = - new ArrayList(IMPLICIT_OBJECT_PERMISSIONS.length); + new ArrayList<>(IMPLICIT_OBJECT_PERMISSIONS.length); - UserModel userModel = user.getUser().getModel(); + for (ObjectPermission.Type permission : IMPLICIT_OBJECT_PERMISSIONS) { // Create model which grants this permission to the current user @@ -445,7 +453,7 @@ public abstract class ModeledDirectoryObjectService implicitPermissions = getImplicitPermissions(user, model); + if (!implicitPermissions.isEmpty()) + getPermissionMapper().insert(implicitPermissions); // Add any arbitrary attributes if (model.hasArbitraryAttributes()) diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/user/ModeledUser.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/user/ModeledUser.java index b7924edd9..54f052b75 100644 --- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/user/ModeledUser.java +++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/user/ModeledUser.java @@ -763,5 +763,16 @@ public class ModeledUser extends ModeledPermissions implements User { public Permissions getEffectivePermissions() throws GuacamoleException { return super.getEffective(); } + + /** + * Returns true if this user is a skeleton user, lacking a database entity + * entry. + * + * @return + * True if this user is a skeleton user, otherwise false. + */ + public boolean isSkeleton() { + return (getModel().getEntityID() == null); + } } diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/user/UserService.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/user/UserService.java index 0aecd10fa..50b9e4295 100644 --- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/user/UserService.java +++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/user/UserService.java @@ -296,8 +296,9 @@ public class UserService extends ModeledDirectoryObjectService getImplicitPermissions(ModeledAuthenticatedUser user, UserModel model) { - // Get original set of implicit permissions - Collection implicitPermissions = super.getImplicitPermissions(user, model); + // Get original set of implicit permissions and make a copy + Collection implicitPermissions = + new ArrayList<>(super.getImplicitPermissions(user, model)); // Grant implicit permissions to the new user for (ObjectPermission.Type permissionType : IMPLICIT_USER_PERMISSIONS) { @@ -312,7 +313,7 @@ public class UserService extends ModeledDirectoryObjectService