GUACAMOLE-708: Merge automatic creation of non-existent authenticated users within database.

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 1bb2c68..3f54be8 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.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 @@
         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 @@
         }
         
         // 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 9158afb..7c9a4b1 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 @@
      *     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 f8d0e8a..133e662 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 @@
     }
 
     /**
-     * Returns a collection of permissions that should be granted due to the
-     * creation of the given object. These permissions need not be granted
-     * solely to the user creating the object.
+     * Returns an immutable collection of permissions that should be granted due
+     * to the creation of the given object.  These permissions need not be
+     * granted solely to the user creating the object.
      * 
      * @param user
      *     The user creating the object.
@@ -427,11 +427,19 @@
     protected Collection<ObjectPermissionModel> 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<ObjectPermissionModel> implicitPermissions =
-                new ArrayList<ObjectPermissionModel>(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 @@
 
         }
         
-        return implicitPermissions;
+        return Collections.unmodifiableCollection(implicitPermissions);
 
     }
 
@@ -464,7 +472,9 @@
         object.setIdentifier(model.getIdentifier());
 
         // Add implicit permissions
-        getPermissionMapper().insert(getImplicitPermissions(user, model));
+        Collection<ObjectPermissionModel> 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 b7924ed..54f052b 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 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 0aecd10..50b9e42 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 @@
     protected Collection<ObjectPermissionModel>
         getImplicitPermissions(ModeledAuthenticatedUser user, UserModel model) {
             
-        // Get original set of implicit permissions
-        Collection<ObjectPermissionModel> implicitPermissions = super.getImplicitPermissions(user, model);
+        // Get original set of implicit permissions and make a copy
+        Collection<ObjectPermissionModel> 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 @@
             
         }
         
-        return implicitPermissions;
+        return Collections.unmodifiableCollection(implicitPermissions);
     }
         
     @Override
@@ -407,11 +408,8 @@
         if (authenticatedUser instanceof ModeledAuthenticatedUser)
             return ((ModeledAuthenticatedUser) authenticatedUser).getUser();
 
-        // Get username
-        String username = authenticatedUser.getIdentifier();
-
         // Retrieve corresponding user model, if such a user exists
-        UserModel userModel = userMapper.selectOne(username);
+        UserModel userModel = userMapper.selectOne(authenticatedUser.getIdentifier());
         if (userModel == null)
             return null;
 
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/src/main/java/org/apache/guacamole/auth/mysql/conf/MySQLEnvironment.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/src/main/java/org/apache/guacamole/auth/mysql/conf/MySQLEnvironment.java
index a538ff3..0159c24 100644
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/src/main/java/org/apache/guacamole/auth/mysql/conf/MySQLEnvironment.java
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/src/main/java/org/apache/guacamole/auth/mysql/conf/MySQLEnvironment.java
@@ -386,5 +386,11 @@
     public String getMYSQLSSLClientPassword() throws GuacamoleException {
         return getProperty(MySQLGuacamoleProperties.MYSQL_SSL_TRUST_PASSWORD);
     }
+    
+    @Override
+    public boolean autoCreateAbsentAccounts() throws GuacamoleException {
+        return getProperty(MySQLGuacamoleProperties.MYSQL_AUTO_CREATE_ACCOUNTS,
+                false);
+    }
 
 }
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/src/main/java/org/apache/guacamole/auth/mysql/conf/MySQLGuacamoleProperties.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/src/main/java/org/apache/guacamole/auth/mysql/conf/MySQLGuacamoleProperties.java
index c87f4cf..d222a0c 100644
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/src/main/java/org/apache/guacamole/auth/mysql/conf/MySQLGuacamoleProperties.java
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/src/main/java/org/apache/guacamole/auth/mysql/conf/MySQLGuacamoleProperties.java
@@ -240,5 +240,18 @@
         public String getName() { return "mysql-ssl-client-password"; }
         
     };
+    
+    /**
+     * Whether or not to automatically create accounts in the MySQL database for
+     * users who successfully authenticate through another extension. By default
+     * users will not be automatically created.
+     */
+    public static final BooleanGuacamoleProperty MYSQL_AUTO_CREATE_ACCOUNTS =
+            new BooleanGuacamoleProperty() {
+    
+        @Override
+        public String getName() { return "mysql-auto-create-accounts"; }
+                
+    };
 
 }
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/src/main/java/org/apache/guacamole/auth/postgresql/conf/PostgreSQLEnvironment.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/src/main/java/org/apache/guacamole/auth/postgresql/conf/PostgreSQLEnvironment.java
index 24e286e..0ac1272 100644
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/src/main/java/org/apache/guacamole/auth/postgresql/conf/PostgreSQLEnvironment.java
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/src/main/java/org/apache/guacamole/auth/postgresql/conf/PostgreSQLEnvironment.java
@@ -328,4 +328,10 @@
         return getProperty(PostgreSQLGuacamoleProperties.POSTGRESQL_SSL_KEY_PASSWORD);
     }
     
+    @Override
+    public boolean autoCreateAbsentAccounts() throws GuacamoleException {
+        return getProperty(PostgreSQLGuacamoleProperties.POSTGRESQL_AUTO_CREATE_ACCOUNTS,
+                false);
+    }
+    
 }
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/src/main/java/org/apache/guacamole/auth/postgresql/conf/PostgreSQLGuacamoleProperties.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/src/main/java/org/apache/guacamole/auth/postgresql/conf/PostgreSQLGuacamoleProperties.java
index 8bd1ff4..fe3ce72 100644
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/src/main/java/org/apache/guacamole/auth/postgresql/conf/PostgreSQLGuacamoleProperties.java
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/src/main/java/org/apache/guacamole/auth/postgresql/conf/PostgreSQLGuacamoleProperties.java
@@ -233,4 +233,17 @@
         
     };
     
+    /**
+     * Whether or not to automatically create accounts in the PostgreSQL
+     * database for users who successfully authenticate through another
+     * extension. By default users will not be automatically created.
+     */
+    public static final BooleanGuacamoleProperty POSTGRESQL_AUTO_CREATE_ACCOUNTS =
+            new BooleanGuacamoleProperty() {
+                
+        @Override
+        public String getName() { return "postgresql-auto-create-accounts"; }
+                
+    };
+    
 }
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-sqlserver/src/main/java/org/apache/guacamole/auth/sqlserver/SQLServerAuthenticationProviderModule.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-sqlserver/src/main/java/org/apache/guacamole/auth/sqlserver/SQLServerAuthenticationProviderModule.java
index 2f9147a..bcd4bc9 100644
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-sqlserver/src/main/java/org/apache/guacamole/auth/sqlserver/SQLServerAuthenticationProviderModule.java
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-sqlserver/src/main/java/org/apache/guacamole/auth/sqlserver/SQLServerAuthenticationProviderModule.java
@@ -25,6 +25,8 @@
 import java.lang.UnsupportedOperationException;
 import java.util.Properties;
 import org.apache.guacamole.GuacamoleException;
+import org.apache.guacamole.auth.sqlserver.conf.SQLServerDriver;
+import org.apache.guacamole.auth.sqlserver.conf.SQLServerEnvironment;
 import org.mybatis.guice.datasource.helper.JdbcHelper;
 
 /**
@@ -45,7 +47,7 @@
     /**
      * Which SQL Server driver should be used.
      */
-    private SQLServerDriver sqlServerDriver;
+    private final SQLServerDriver sqlServerDriver;
 
     /**
      * Creates a new SQLServer authentication provider module that configures
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-sqlserver/src/main/java/org/apache/guacamole/auth/sqlserver/SQLServerInjectorProvider.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-sqlserver/src/main/java/org/apache/guacamole/auth/sqlserver/SQLServerInjectorProvider.java
index 32d12f6..667174e 100644
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-sqlserver/src/main/java/org/apache/guacamole/auth/sqlserver/SQLServerInjectorProvider.java
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-sqlserver/src/main/java/org/apache/guacamole/auth/sqlserver/SQLServerInjectorProvider.java
@@ -24,6 +24,7 @@
 import org.apache.guacamole.GuacamoleException;
 import org.apache.guacamole.auth.jdbc.JDBCAuthenticationProviderModule;
 import org.apache.guacamole.auth.jdbc.JDBCInjectorProvider;
+import org.apache.guacamole.auth.sqlserver.conf.SQLServerEnvironment;
 
 /**
  * JDBCInjectorProvider implementation which configures Guice injections for
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-sqlserver/src/main/java/org/apache/guacamole/auth/sqlserver/SQLServerDriver.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-sqlserver/src/main/java/org/apache/guacamole/auth/sqlserver/conf/SQLServerDriver.java
similarity index 96%
rename from extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-sqlserver/src/main/java/org/apache/guacamole/auth/sqlserver/SQLServerDriver.java
rename to extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-sqlserver/src/main/java/org/apache/guacamole/auth/sqlserver/conf/SQLServerDriver.java
index d1fdc8f..4a4321e 100644
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-sqlserver/src/main/java/org/apache/guacamole/auth/sqlserver/SQLServerDriver.java
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-sqlserver/src/main/java/org/apache/guacamole/auth/sqlserver/conf/SQLServerDriver.java
@@ -17,7 +17,7 @@
  * under the License.
  */
 
-package org.apache.guacamole.auth.sqlserver;
+package org.apache.guacamole.auth.sqlserver.conf;
 
 import org.apache.guacamole.properties.EnumGuacamoleProperty.PropertyValue;
 
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-sqlserver/src/main/java/org/apache/guacamole/auth/sqlserver/SQLServerEnvironment.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-sqlserver/src/main/java/org/apache/guacamole/auth/sqlserver/conf/SQLServerEnvironment.java
similarity index 97%
rename from extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-sqlserver/src/main/java/org/apache/guacamole/auth/sqlserver/SQLServerEnvironment.java
rename to extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-sqlserver/src/main/java/org/apache/guacamole/auth/sqlserver/conf/SQLServerEnvironment.java
index 9b61be0..563db0e 100644
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-sqlserver/src/main/java/org/apache/guacamole/auth/sqlserver/SQLServerEnvironment.java
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-sqlserver/src/main/java/org/apache/guacamole/auth/sqlserver/conf/SQLServerEnvironment.java
@@ -17,7 +17,7 @@
  * under the License.
  */
 
-package org.apache.guacamole.auth.sqlserver;
+package org.apache.guacamole.auth.sqlserver.conf;
 
 import org.apache.guacamole.GuacamoleException;
 import org.apache.guacamole.auth.jdbc.JDBCEnvironment;
@@ -273,5 +273,11 @@
     public boolean isRecursiveQuerySupported(SqlSession session) {
         return true; // All versions of SQL Server support recursive queries through CTEs
     }
+    
+    @Override
+    public boolean autoCreateAbsentAccounts() throws GuacamoleException {
+        return getProperty(SQLServerGuacamoleProperties.SQLSERVER_AUTO_CREATE_ACCOUNTS,
+                false);
+    }
 
 }
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-sqlserver/src/main/java/org/apache/guacamole/auth/sqlserver/SQLServerGuacamoleProperties.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-sqlserver/src/main/java/org/apache/guacamole/auth/sqlserver/conf/SQLServerGuacamoleProperties.java
similarity index 91%
rename from extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-sqlserver/src/main/java/org/apache/guacamole/auth/sqlserver/SQLServerGuacamoleProperties.java
rename to extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-sqlserver/src/main/java/org/apache/guacamole/auth/sqlserver/conf/SQLServerGuacamoleProperties.java
index 257c07e..df63c53 100644
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-sqlserver/src/main/java/org/apache/guacamole/auth/sqlserver/SQLServerGuacamoleProperties.java
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-sqlserver/src/main/java/org/apache/guacamole/auth/sqlserver/conf/SQLServerGuacamoleProperties.java
@@ -17,7 +17,7 @@
  * under the License.
  */
 
-package org.apache.guacamole.auth.sqlserver;
+package org.apache.guacamole.auth.sqlserver.conf;
 
 import org.apache.guacamole.properties.BooleanGuacamoleProperty;
 import org.apache.guacamole.properties.EnumGuacamoleProperty;
@@ -193,5 +193,18 @@
         public String getName() { return "sqlserver-driver"; }
 
     };
+    
+    /**
+     * Whether or not to automatically create accounts in the SQL Server
+     * database for users who successfully authenticate through another
+     * extension. By default users will not be automatically created.
+     */
+    public static final BooleanGuacamoleProperty SQLSERVER_AUTO_CREATE_ACCOUNTS =
+            new BooleanGuacamoleProperty() {
+        
+        @Override
+        public String getName() { return "sqlserver-auto-create-accounts"; }
+        
+    };
 
 }
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-sqlserver/src/main/java/org/apache/guacamole/auth/sqlserver/SQLServerPasswordPolicy.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-sqlserver/src/main/java/org/apache/guacamole/auth/sqlserver/conf/SQLServerPasswordPolicy.java
similarity index 98%
rename from extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-sqlserver/src/main/java/org/apache/guacamole/auth/sqlserver/SQLServerPasswordPolicy.java
rename to extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-sqlserver/src/main/java/org/apache/guacamole/auth/sqlserver/conf/SQLServerPasswordPolicy.java
index f30b180..e18649b 100644
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-sqlserver/src/main/java/org/apache/guacamole/auth/sqlserver/SQLServerPasswordPolicy.java
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-sqlserver/src/main/java/org/apache/guacamole/auth/sqlserver/conf/SQLServerPasswordPolicy.java
@@ -17,7 +17,7 @@
  * under the License.
  */
 
-package org.apache.guacamole.auth.sqlserver;
+package org.apache.guacamole.auth.sqlserver.conf;
 
 import org.apache.guacamole.GuacamoleException;
 import org.apache.guacamole.auth.jdbc.JDBCEnvironment;