diff --git a/doc/guacamole-example/pom.xml b/doc/guacamole-example/pom.xml
index ec12bfbbb..e4a4f1c12 100644
--- a/doc/guacamole-example/pom.xml
+++ b/doc/guacamole-example/pom.xml
@@ -26,7 +26,7 @@
org.apache.guacamole
guacamole-example
war
- 1.5.5
+ 1.6.0
guacamole-example
http://guacamole.apache.org/
@@ -106,7 +106,7 @@
org.apache.guacamole
guacamole-common
- 1.5.5
+ 1.6.0
compile
@@ -114,7 +114,7 @@
org.apache.guacamole
guacamole-common-js
- 1.5.5
+ 1.6.0
zip
runtime
diff --git a/doc/guacamole-playback-example/pom.xml b/doc/guacamole-playback-example/pom.xml
index 90d455bc2..8563e078c 100644
--- a/doc/guacamole-playback-example/pom.xml
+++ b/doc/guacamole-playback-example/pom.xml
@@ -26,7 +26,7 @@
org.apache.guacamole
guacamole-playback-example
war
- 1.5.5
+ 1.6.0
guacamole-playback-example
http://guacamole.apache.org/
@@ -88,7 +88,7 @@
org.apache.guacamole
guacamole-common-js
- 1.5.5
+ 1.6.0
zip
runtime
diff --git a/extensions/guacamole-auth-ban/pom.xml b/extensions/guacamole-auth-ban/pom.xml
index 8b7e90f4e..a9e8dfe3d 100644
--- a/extensions/guacamole-auth-ban/pom.xml
+++ b/extensions/guacamole-auth-ban/pom.xml
@@ -26,14 +26,14 @@
org.apache.guacamole
guacamole-auth-ban
jar
- 1.5.5
+ 1.6.0
guacamole-auth-ban
http://guacamole.apache.org/
org.apache.guacamole
extensions
- 1.5.5
+ 1.6.0
../
@@ -51,7 +51,7 @@
org.apache.guacamole
guacamole-ext
- 1.5.5
+ 1.6.0
provided
+
+ com.github.seancfoley
+ ipaddress
+ 5.5.0
+ provided
+
+
diff --git a/extensions/guacamole-auth-duo/src/main/java/org/apache/guacamole/auth/duo/UserVerificationService.java b/extensions/guacamole-auth-duo/src/main/java/org/apache/guacamole/auth/duo/UserVerificationService.java
index 2333e21ef..d2a6fa74d 100644
--- a/extensions/guacamole-auth-duo/src/main/java/org/apache/guacamole/auth/duo/UserVerificationService.java
+++ b/extensions/guacamole-auth-duo/src/main/java/org/apache/guacamole/auth/duo/UserVerificationService.java
@@ -23,10 +23,13 @@ import com.duosecurity.Client;
import com.duosecurity.exception.DuoException;
import com.duosecurity.model.Token;
import com.google.inject.Inject;
+import inet.ipaddr.IPAddress;
+import inet.ipaddr.IPAddressString;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Collections;
import java.util.concurrent.TimeUnit;
+import java.util.List;
import javax.servlet.http.HttpServletRequest;
import org.apache.guacamole.GuacamoleException;
import org.apache.guacamole.GuacamoleServerException;
@@ -37,6 +40,7 @@ import org.apache.guacamole.language.TranslatableMessage;
import org.apache.guacamole.net.auth.AuthenticatedUser;
import org.apache.guacamole.net.auth.Credentials;
import org.apache.guacamole.net.auth.credentials.CredentialsInfo;
+import org.apache.guacamole.properties.IPAddressListProperty;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -107,9 +111,41 @@ public class UserVerificationService {
public void verifyAuthenticatedUser(AuthenticatedUser authenticatedUser)
throws GuacamoleException {
- // Ignore anonymous users (unverifiable)
+ // Pull the original HTTP request used to authenticate
+ Credentials credentials = authenticatedUser.getCredentials();
+ HttpServletRequest request = credentials.getRequest();
+ IPAddress clientAddr = new IPAddressString(request.getRemoteAddr()).getAddress();
+
+ // Ignore anonymous users
String username = authenticatedUser.getIdentifier();
- if (username.equals(AuthenticatedUser.ANONYMOUS_IDENTIFIER))
+ if (username == null || username.equals(AuthenticatedUser.ANONYMOUS_IDENTIFIER))
+ return;
+
+ // Pull address lists to check from configuration. Note that the enforce
+ // list will override the bypass list, which means that, if the client
+ // address happens to be in both lists, Duo MFA will be enforced.
+ List bypassAddresses = confService.getBypassHosts();
+ List enforceAddresses = confService.getEnforceHosts();
+
+ // Check if the bypass list contains the client address, and set the
+ // enforce flag to the opposite.
+ boolean enforceHost = !(IPAddressListProperty.addressListContains(bypassAddresses, clientAddr));
+
+ // Only continue processing if the list is not empty
+ if (!enforceAddresses.isEmpty()) {
+
+ // If client address is not available or invalid, MFA will
+ // be enforced.
+ if (clientAddr == null || !clientAddr.isIPAddress())
+ enforceHost = true;
+
+ // Check the enforce list for the client address and set enforcement flag.
+ else
+ enforceHost = IPAddressListProperty.addressListContains(enforceAddresses, clientAddr);
+ }
+
+ // If the enforce flag is not true, bypass Duo MFA.
+ if (!enforceHost)
return;
// Obtain a Duo client for redirecting the user to the Duo service and
@@ -137,11 +173,6 @@ public class UserVerificationService {
+ "not currently available (failed health check).", e);
}
- // Pull the original HTTP request used to authenticate, as well as any
- // associated credentials
- Credentials credentials = authenticatedUser.getCredentials();
- HttpServletRequest request = credentials.getRequest();
-
// Retrieve signed Duo authentication code and session state from the
// request (these will be absent if this is an initial authentication
// attempt and not a redirect back from Duo)
diff --git a/extensions/guacamole-auth-duo/src/main/java/org/apache/guacamole/auth/duo/conf/ConfigurationService.java b/extensions/guacamole-auth-duo/src/main/java/org/apache/guacamole/auth/duo/conf/ConfigurationService.java
index 5ed7d7a21..43a2d98ed 100644
--- a/extensions/guacamole-auth-duo/src/main/java/org/apache/guacamole/auth/duo/conf/ConfigurationService.java
+++ b/extensions/guacamole-auth-duo/src/main/java/org/apache/guacamole/auth/duo/conf/ConfigurationService.java
@@ -20,10 +20,14 @@
package org.apache.guacamole.auth.duo.conf;
import com.google.inject.Inject;
+import inet.ipaddr.IPAddress;
import java.net.URI;
+import java.util.Collections;
+import java.util.List;
import org.apache.guacamole.GuacamoleException;
import org.apache.guacamole.environment.Environment;
import org.apache.guacamole.properties.IntegerGuacamoleProperty;
+import org.apache.guacamole.properties.IPAddressListProperty;
import org.apache.guacamole.properties.StringGuacamoleProperty;
import org.apache.guacamole.properties.URIGuacamoleProperty;
@@ -105,6 +109,40 @@ public class ConfigurationService {
public String getName() { return "duo-auth-timeout"; }
};
+
+ /**
+ * The optional property that contains a comma-separated list of IP addresses
+ * or CIDRs for which the MFA requirement should be bypassed. If the Duo
+ * extension is installed, any/all users authenticating from clients that
+ * match this list will be able to successfully log in without fulfilling
+ * the MFA requirement. If this option is omitted or is empty, and the
+ * Duo module is installed, all users from all hosts will have Duo MFA
+ * enforced.
+ */
+ private static final IPAddressListProperty DUO_BYPASS_HOSTS =
+ new IPAddressListProperty() {
+
+ @Override
+ public String getName() { return "duo-bypass-hosts"; }
+
+ };
+
+ /**
+ * The optional property that contains a comma-separated list of IP addresses
+ * or CIDRs for which the MFA requirement should be explicitly enforced. If
+ * the Duo module is enabled and this property is specified, users that log
+ * in from hosts that match the items in this list will have Duo MFA required,
+ * and all users from hosts that do not match this list will be able to log
+ * in without the MFA requirement. If this option is missing or empty and
+ * the Duo module is installed, MFA will be enforced for all users.
+ */
+ private static final IPAddressListProperty DUO_ENFORCE_HOSTS =
+ new IPAddressListProperty() {
+
+ @Override
+ public String getName() { return "duo-enforce-hosts"; }
+
+ };
/**
* Returns the hostname of the Duo API endpoint to be used to verify user
@@ -188,5 +226,43 @@ public class ConfigurationService {
public int getAuthenticationTimeout() throws GuacamoleException {
return environment.getProperty(DUO_AUTH_TIMEOUT, 5);
}
+
+ /**
+ * Returns the list of IP addresses and subnets defined in guacamole.properties
+ * for which Duo MFA should _not_ be enforced. Users logging in from hosts
+ * contained in this list will be logged in without the MFA requirement.
+ *
+ * @return
+ * A list of IP addresses and subnets for which Duo MFA should not be
+ * enforced.
+ *
+ * @throws GuacamoleException
+ * If guacamole.properties cannot be parsed, or if an invalid IP address
+ * or subnet is specified.
+ */
+ public List getBypassHosts() throws GuacamoleException {
+ return environment.getProperty(DUO_BYPASS_HOSTS, Collections.emptyList());
+ }
+
+ /**
+ * Returns the list of IP addresses and subnets defined in guacamole.properties
+ * for which Duo MFA should explicitly be enforced, while logins from all
+ * other hosts should not enforce MFA. Users logging in from hosts
+ * contained in this list will be required to complete the Duo MFA authentication,
+ * while users from all other hosts will be logged in without the MFA requirement.
+ *
+ * @return
+ * A list of IP addresses and subnets for which Duo MFA should be
+ * explicitly enforced.
+ *
+ * @throws GuacamoleException
+ * If guacamole.properties cannot be parsed, or if an invalid IP address
+ * or subnet is specified.
+ */
+ public List getEnforceHosts() throws GuacamoleException {
+ return environment.getProperty(DUO_ENFORCE_HOSTS, Collections.emptyList());
+ }
+
+
}
diff --git a/extensions/guacamole-auth-duo/src/main/resources/guac-manifest.json b/extensions/guacamole-auth-duo/src/main/resources/guac-manifest.json
index 2a9d727a9..5c305ed97 100644
--- a/extensions/guacamole-auth-duo/src/main/resources/guac-manifest.json
+++ b/extensions/guacamole-auth-duo/src/main/resources/guac-manifest.json
@@ -1,6 +1,6 @@
{
- "guacamoleVersion" : "1.5.5",
+ "guacamoleVersion" : "1.6.0",
"name" : "Duo TFA Authentication Backend",
"namespace" : "duo",
diff --git a/extensions/guacamole-auth-header/pom.xml b/extensions/guacamole-auth-header/pom.xml
index b28a535bb..017ea64a5 100644
--- a/extensions/guacamole-auth-header/pom.xml
+++ b/extensions/guacamole-auth-header/pom.xml
@@ -26,14 +26,14 @@
org.apache.guacamole
guacamole-auth-header
jar
- 1.5.5
+ 1.6.0
guacamole-auth-header
http://guacamole.apache.org/
org.apache.guacamole
extensions
- 1.5.5
+ 1.6.0
../
@@ -43,7 +43,7 @@
org.apache.guacamole
guacamole-ext
- 1.5.5
+ 1.6.0
provided
diff --git a/extensions/guacamole-auth-header/src/main/resources/guac-manifest.json b/extensions/guacamole-auth-header/src/main/resources/guac-manifest.json
index 39a2bac43..49015dec9 100644
--- a/extensions/guacamole-auth-header/src/main/resources/guac-manifest.json
+++ b/extensions/guacamole-auth-header/src/main/resources/guac-manifest.json
@@ -1,6 +1,6 @@
{
- "guacamoleVersion" : "1.5.5",
+ "guacamoleVersion" : "1.6.0",
"name" : "HTTP Header Authentication Extension",
"namespace" : "header",
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/pom.xml b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/pom.xml
index ae0eacce1..956feacb8 100644
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/pom.xml
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/pom.xml
@@ -32,7 +32,7 @@
org.apache.guacamole
guacamole-auth-jdbc
- 1.5.5
+ 1.6.0
../../
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/connection/ConnectionService.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/connection/ConnectionService.java
index f7c1203f5..31f4df49c 100644
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/connection/ConnectionService.java
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/connection/ConnectionService.java
@@ -483,8 +483,8 @@ public class ConnectionService extends ModeledChildDirectoryObjectService searchResults;
- // Bypass permission checks if the user is privileged
- if (user.isPrivileged())
+ // Bypass permission checks if the user is privileged or has System-level audit permissions
+ if (user.isPrivileged() || user.getUser().getEffectivePermissions().getSystemPermissions().hasPermission(SystemPermission.Type.AUDIT))
searchResults = connectionRecordMapper.search(identifier,
recordIdentifier, requiredContents, sortPredicates, limit);
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/tunnel/AbstractGuacamoleTunnelService.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/tunnel/AbstractGuacamoleTunnelService.java
index 8c16363a6..d9323f4b4 100644
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/tunnel/AbstractGuacamoleTunnelService.java
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/tunnel/AbstractGuacamoleTunnelService.java
@@ -21,6 +21,7 @@ package org.apache.guacamole.auth.jdbc.tunnel;
import com.google.inject.Inject;
import com.google.inject.Provider;
+import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
@@ -81,6 +82,56 @@ public abstract class AbstractGuacamoleTunnelService implements GuacamoleTunnelS
*/
private final Logger logger = LoggerFactory.getLogger(AbstractGuacamoleTunnelService.class);
+ /**
+ * The prefix that will be used to generate JDBC tokens.
+ */
+ private final String JDBC_TOKEN_PREFIX = "JDBC_";
+
+ /**
+ * The token that contains the date the connection was started.
+ */
+ private final String JDBC_DATE_TOKEN = JDBC_TOKEN_PREFIX + "STARTDATE";
+
+ /**
+ * The format of the date in the date token.
+ */
+ private final String JDBC_DATE_TOKEN_FORMAT = "yyyyMMdd";
+
+ /**
+ * The token that contains the start time of the connection.
+ */
+ private final String JDBC_TIME_TOKEN = JDBC_TOKEN_PREFIX + "STARTTIME";
+
+ /**
+ * The format of the time in the time token.
+ */
+ private final String JDBC_TIME_TOKEN_FORMAT = "HHmmss";
+
+ /**
+ * The token that contains the connection name.
+ */
+ private final String JDBC_CONNECTION_NAME_TOKEN = JDBC_TOKEN_PREFIX + "CONNECTION_NAME";
+
+ /**
+ * The token that contains the connection identifier.
+ */
+ private final String JDBC_CONNECTION_ID_TOKEN = JDBC_TOKEN_PREFIX + "CONNECTION_ID";
+
+ /**
+ * The token that contains the hostname configured in the connection parameters.
+ */
+ private final String JDBC_CONNECTION_HOSTNAME_TOKEN = JDBC_TOKEN_PREFIX + "HOSTNAME";
+
+ /**
+ * The name of the parameter containing the hostname in the configuration.
+ */
+ private final String JDBC_CONNECTION_HOSTNAME_TOKEN_PARAMETER = "hostname";
+
+ /**
+ * The token containing the protocol configured in the connection.
+ */
+ private final String JDBC_CONNECTION_PROTOCOL_TOKEN = JDBC_TOKEN_PREFIX + "PROTOCOL";
+
/**
* Mapper for accessing connections.
*/
@@ -121,7 +172,7 @@ public abstract class AbstractGuacamoleTunnelService implements GuacamoleTunnelS
* All active connections through the tunnel having a given UUID.
*/
private final Map activeTunnels =
- new ConcurrentHashMap();
+ new ConcurrentHashMap<>();
/**
* All active connections to a connection having a given identifier.
@@ -415,7 +466,7 @@ public abstract class AbstractGuacamoleTunnelService implements GuacamoleTunnelS
private GuacamoleTunnel assignGuacamoleTunnel(ActiveConnectionRecord activeConnection,
GuacamoleClientInformation info, Map tokens,
boolean interceptErrors) throws GuacamoleException {
-
+
// Record new active connection
Runnable cleanupTask = new ConnectionCleanupTask(activeConnection);
try {
@@ -459,9 +510,25 @@ public abstract class AbstractGuacamoleTunnelService implements GuacamoleTunnelS
config = getGuacamoleConfiguration(connection, connectionID, activeConnection.getSharingProfile());
}
-
- // Include history record UUID as token
+
+ // Make a copy of the tokens
tokens = new HashMap<>(tokens);
+
+ // Set up JDBC-specific tokens
+ tokens.put(JDBC_DATE_TOKEN,
+ new SimpleDateFormat(JDBC_DATE_TOKEN_FORMAT)
+ .format(activeConnection.getStartDate()));
+ tokens.put(JDBC_TIME_TOKEN,
+ new SimpleDateFormat(JDBC_TIME_TOKEN_FORMAT)
+ .format(activeConnection.getStartDate()));
+ tokens.put(JDBC_CONNECTION_NAME_TOKEN, activeConnection.getConnectionName());
+ tokens.put(JDBC_CONNECTION_ID_TOKEN, activeConnection.getConnectionIdentifier());
+ tokens.put(JDBC_CONNECTION_HOSTNAME_TOKEN,
+ activeConnection.getConnection().getConfiguration().getParameter(JDBC_CONNECTION_HOSTNAME_TOKEN_PARAMETER));
+ tokens.put(JDBC_CONNECTION_PROTOCOL_TOKEN,
+ activeConnection.getConnection().getConfiguration().getProtocol());
+
+ // Include history record UUID as token
tokens.put("HISTORY_UUID", activeConnection.getUUID().toString());
// Build token filter containing credential tokens
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 161976ce4..08acff2a6 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
@@ -611,8 +611,8 @@ public class UserService extends ModeledDirectoryObjectService searchResults;
- // Bypass permission checks if the user is privileged
- if (user.isPrivileged())
+ // Bypass permission checks if the user is privileged or has System-level audit permissions
+ if (user.isPrivileged() || user.getUser().getEffectivePermissions().getSystemPermissions().hasPermission(SystemPermission.Type.AUDIT))
searchResults = userRecordMapper.search(username, recordIdentifier,
requiredContents, sortPredicates, limit);
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-dist/pom.xml b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-dist/pom.xml
index 9d04a8f7c..93a4e752f 100644
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-dist/pom.xml
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-dist/pom.xml
@@ -32,7 +32,7 @@
org.apache.guacamole
guacamole-auth-jdbc
- 1.5.5
+ 1.6.0
../../
@@ -42,21 +42,21 @@
org.apache.guacamole
guacamole-auth-jdbc-mysql
- 1.5.5
+ 1.6.0
org.apache.guacamole
guacamole-auth-jdbc-postgresql
- 1.5.5
+ 1.6.0
org.apache.guacamole
guacamole-auth-jdbc-sqlserver
- 1.5.5
+ 1.6.0
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/pom.xml b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/pom.xml
index 1cb7e20c9..0818ac3c2 100644
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/pom.xml
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/pom.xml
@@ -32,7 +32,7 @@
org.apache.guacamole
guacamole-auth-jdbc
- 1.5.5
+ 1.6.0
../../
@@ -49,7 +49,7 @@
org.apache.guacamole
guacamole-auth-jdbc-base
- 1.5.5
+ 1.6.0
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/schema/001-create-schema.sql b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/schema/001-create-schema.sql
index 1606af1f3..8241961f4 100644
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/schema/001-create-schema.sql
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/schema/001-create-schema.sql
@@ -459,6 +459,7 @@ CREATE TABLE `guacamole_system_permission` (
'CREATE_SHARING_PROFILE',
'CREATE_USER',
'CREATE_USER_GROUP',
+ 'AUDIT',
'ADMINISTER') NOT NULL,
PRIMARY KEY (`entity_id`,`permission`),
@@ -611,3 +612,4 @@ CREATE TABLE guacamole_user_password_history (
REFERENCES `guacamole_user` (`user_id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/schema/002-create-admin-user.sql b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/schema/002-create-admin-user.sql
index f62d6d1d2..2b7cc0250 100644
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/schema/002-create-admin-user.sql
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/schema/002-create-admin-user.sql
@@ -51,3 +51,4 @@ FROM (
JOIN guacamole_entity ON permissions.username = guacamole_entity.name AND guacamole_entity.type = 'USER'
JOIN guacamole_entity affected ON permissions.affected_username = affected.name AND guacamole_entity.type = 'USER'
JOIN guacamole_user ON guacamole_user.entity_id = affected.entity_id;
+
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/schema/upgrade/upgrade-pre-1.6.0.sql b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/schema/upgrade/upgrade-pre-1.6.0.sql
new file mode 100644
index 000000000..3533e48e5
--- /dev/null
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/schema/upgrade/upgrade-pre-1.6.0.sql
@@ -0,0 +1,32 @@
+--
+-- Licensed to the Apache Software Foundation (ASF) under one
+-- or more contributor license agreements. See the NOTICE file
+-- distributed with this work for additional information
+-- regarding copyright ownership. The ASF licenses this file
+-- to you under the Apache License, Version 2.0 (the
+-- "License"); you may not use this file except in compliance
+-- with the License. You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing,
+-- software distributed under the License is distributed on an
+-- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+-- KIND, either express or implied. See the License for the
+-- specific language governing permissions and limitations
+-- under the License.
+--
+
+--
+-- Add new system-level permission
+--
+
+ALTER TABLE `guacamole_system_permission`
+ MODIFY `permission` enum('CREATE_CONNECTION',
+ 'CREATE_CONNECTION_GROUP',
+ 'CREATE_SHARING_PROFILE',
+ 'CREATE_USER',
+ 'CREATE_USER_GROUP',
+ 'AUDIT',
+ 'ADMINISTER') NOT NULL;
+
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/src/main/resources/guac-manifest.json b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/src/main/resources/guac-manifest.json
index 6711a36df..1cd1ddfeb 100644
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/src/main/resources/guac-manifest.json
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/src/main/resources/guac-manifest.json
@@ -1,6 +1,6 @@
{
- "guacamoleVersion" : "1.5.5",
+ "guacamoleVersion" : "1.6.0",
"name" : "MySQL Authentication",
"namespace" : "mysql",
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/pom.xml b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/pom.xml
index 986e4ac0b..5d3129bd4 100644
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/pom.xml
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/pom.xml
@@ -32,7 +32,7 @@
org.apache.guacamole
guacamole-auth-jdbc
- 1.5.5
+ 1.6.0
../../
@@ -49,7 +49,7 @@
org.apache.guacamole
guacamole-auth-jdbc-base
- 1.5.5
+ 1.6.0
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/schema/001-create-schema.sql b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/schema/001-create-schema.sql
index 9bcf1c51f..134215d29 100644
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/schema/001-create-schema.sql
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/schema/001-create-schema.sql
@@ -56,6 +56,7 @@ CREATE TYPE guacamole_system_permission_type AS ENUM(
'CREATE_SHARING_PROFILE',
'CREATE_USER',
'CREATE_USER_GROUP',
+ 'AUDIT',
'ADMINISTER'
);
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/schema/002-create-admin-user.sql b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/schema/002-create-admin-user.sql
index c7cd7c910..3a58771f1 100644
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/schema/002-create-admin-user.sql
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/schema/002-create-admin-user.sql
@@ -53,3 +53,4 @@ FROM (
JOIN guacamole_entity ON permissions.username = guacamole_entity.name AND guacamole_entity.type = 'USER'
JOIN guacamole_entity affected ON permissions.affected_username = affected.name AND guacamole_entity.type = 'USER'
JOIN guacamole_user ON guacamole_user.entity_id = affected.entity_id;
+
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/schema/upgrade/upgrade-pre-1.6.0.sql b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/schema/upgrade/upgrade-pre-1.6.0.sql
new file mode 100644
index 000000000..9a4536e25
--- /dev/null
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/schema/upgrade/upgrade-pre-1.6.0.sql
@@ -0,0 +1,27 @@
+--
+-- Licensed to the Apache Software Foundation (ASF) under one
+-- or more contributor license agreements. See the NOTICE file
+-- distributed with this work for additional information
+-- regarding copyright ownership. The ASF licenses this file
+-- to you under the Apache License, Version 2.0 (the
+-- "License"); you may not use this file except in compliance
+-- with the License. You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing,
+-- software distributed under the License is distributed on an
+-- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+-- KIND, either express or implied. See the License for the
+-- specific language governing permissions and limitations
+-- under the License.
+--
+
+--
+-- Add new system-level audit permission
+--
+
+ALTER TYPE guacamole_system_permission_type
+ ADD VALUE 'AUDIT'
+ BEFORE 'ADMINISTER';
+
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/src/main/resources/guac-manifest.json b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/src/main/resources/guac-manifest.json
index 5fe5ec183..0f7d160fc 100644
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/src/main/resources/guac-manifest.json
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/src/main/resources/guac-manifest.json
@@ -1,6 +1,6 @@
{
- "guacamoleVersion" : "1.5.5",
+ "guacamoleVersion" : "1.6.0",
"name" : "PostgreSQL Authentication",
"namespace" : "postgresql",
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-sqlserver/pom.xml b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-sqlserver/pom.xml
index aab232d39..8ceee87df 100644
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-sqlserver/pom.xml
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-sqlserver/pom.xml
@@ -32,7 +32,7 @@
org.apache.guacamole
guacamole-auth-jdbc
- 1.5.5
+ 1.6.0
../../
@@ -49,7 +49,7 @@
org.apache.guacamole
guacamole-auth-jdbc-base
- 1.5.5
+ 1.6.0
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-sqlserver/schema/001-create-schema.sql b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-sqlserver/schema/001-create-schema.sql
index 54be792ba..44346538b 100644
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-sqlserver/schema/001-create-schema.sql
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-sqlserver/schema/001-create-schema.sql
@@ -77,6 +77,7 @@ CREATE RULE [guacamole_system_permission_list] AS @list IN (
'CREATE_SHARING_PROFILE',
'CREATE_USER',
'CREATE_USER_GROUP',
+ 'AUDIT',
'ADMINISTER'
);
GO
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-sqlserver/schema/002-create-admin-user.sql b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-sqlserver/schema/002-create-admin-user.sql
index dcb4257d6..70cf520a1 100644
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-sqlserver/schema/002-create-admin-user.sql
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-sqlserver/schema/002-create-admin-user.sql
@@ -61,3 +61,4 @@ JOIN [guacamole_entity] ON [permissions].[username] = [guacamole_enti
JOIN [guacamole_entity] [affected] ON [permissions].[affected_username] = [affected].[name] AND [guacamole_entity].[type] = 'USER'
JOIN [guacamole_user] ON [guacamole_user].[entity_id] = [affected].[entity_id];
GO
+
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-sqlserver/schema/upgrade/upgrade-pre-1.6.0.sql b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-sqlserver/schema/upgrade/upgrade-pre-1.6.0.sql
new file mode 100644
index 000000000..e56f7ee12
--- /dev/null
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-sqlserver/schema/upgrade/upgrade-pre-1.6.0.sql
@@ -0,0 +1,43 @@
+--
+-- Licensed to the Apache Software Foundation (ASF) under one
+-- or more contributor license agreements. See the NOTICE file
+-- distributed with this work for additional information
+-- regarding copyright ownership. The ASF licenses this file
+-- to you under the Apache License, Version 2.0 (the
+-- "License"); you may not use this file except in compliance
+-- with the License. You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing,
+-- software distributed under the License is distributed on an
+-- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+-- KIND, either express or implied. See the License for the
+-- specific language governing permissions and limitations
+-- under the License.
+--
+
+--
+-- Add new system-level audit permission
+--
+
+EXEC sp_unbindrule 'guacamole_system_permission';
+DROP RULE [guacamole_system_permission_list];
+GO
+
+CREATE RULE [guacamole_system_permission_list] AS @list IN (
+ 'CREATE_CONNECTION',
+ 'CREATE_CONNECTION_GROUP',
+ 'CREATE_SHARING_PROFILE',
+ 'CREATE_USER',
+ 'CREATE_USER_GROUP',
+ 'AUDIT',
+ 'ADMINISTER'
+);
+GO
+
+EXEC sp_bindrule
+ 'guacamole_system_permission_list',
+ 'guacamole_system_permission';
+GO
+
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-sqlserver/src/main/resources/guac-manifest.json b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-sqlserver/src/main/resources/guac-manifest.json
index eded5ff3f..8ee7ac176 100644
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-sqlserver/src/main/resources/guac-manifest.json
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-sqlserver/src/main/resources/guac-manifest.json
@@ -1,6 +1,6 @@
{
- "guacamoleVersion" : "1.5.5",
+ "guacamoleVersion" : "1.6.0",
"name" : "SQLServer Authentication",
"namespace" : "sqlserver",
diff --git a/extensions/guacamole-auth-jdbc/pom.xml b/extensions/guacamole-auth-jdbc/pom.xml
index 126df3cc4..e9ac71f58 100644
--- a/extensions/guacamole-auth-jdbc/pom.xml
+++ b/extensions/guacamole-auth-jdbc/pom.xml
@@ -26,14 +26,14 @@
org.apache.guacamole
guacamole-auth-jdbc
pom
- 1.5.5
+ 1.6.0
guacamole-auth-jdbc
http://guacamole.apache.org/
org.apache.guacamole
extensions
- 1.5.5
+ 1.6.0
../
@@ -59,7 +59,7 @@
org.apache.guacamole
guacamole-ext
- 1.5.5
+ 1.6.0
provided
diff --git a/extensions/guacamole-auth-json/pom.xml b/extensions/guacamole-auth-json/pom.xml
index a986b627f..5fc38b011 100644
--- a/extensions/guacamole-auth-json/pom.xml
+++ b/extensions/guacamole-auth-json/pom.xml
@@ -26,14 +26,14 @@
org.apache.guacamole
guacamole-auth-json
jar
- 1.5.5
+ 1.6.0
guacamole-auth-json
http://guacamole.apache.org/
org.apache.guacamole
extensions
- 1.5.5
+ 1.6.0
../
@@ -43,7 +43,7 @@
org.apache.guacamole
guacamole-ext
- 1.5.5
+ 1.6.0
provided
@@ -78,6 +78,7 @@
com.github.seancfoley
ipaddress
5.5.0
+ provided
diff --git a/extensions/guacamole-auth-json/src/main/java/org/apache/guacamole/auth/json/ConfigurationService.java b/extensions/guacamole-auth-json/src/main/java/org/apache/guacamole/auth/json/ConfigurationService.java
index 1483f6fcb..2705e61ed 100644
--- a/extensions/guacamole-auth-json/src/main/java/org/apache/guacamole/auth/json/ConfigurationService.java
+++ b/extensions/guacamole-auth-json/src/main/java/org/apache/guacamole/auth/json/ConfigurationService.java
@@ -25,7 +25,7 @@ import java.util.Collections;
import org.apache.guacamole.GuacamoleException;
import org.apache.guacamole.environment.Environment;
import org.apache.guacamole.properties.ByteArrayProperty;
-import org.apache.guacamole.properties.StringListProperty;
+import org.apache.guacamole.properties.StringGuacamoleProperty;
/**
* Service for retrieving configuration information regarding the JSON
@@ -56,7 +56,7 @@ public class ConfigurationService {
* be allowed to perform authentication. If not specified, ALL address will
* be allowed.
*/
- private static final StringListProperty JSON_TRUSTED_NETWORKS = new StringListProperty() {
+ private static final StringGuacamoleProperty JSON_TRUSTED_NETWORKS = new StringGuacamoleProperty() {
@Override
public String getName() {
@@ -95,7 +95,7 @@ public class ConfigurationService {
* If guacamole.properties cannot be parsed.
*/
public Collection getTrustedNetworks() throws GuacamoleException {
- return environment.getProperty(JSON_TRUSTED_NETWORKS, Collections.emptyList());
+ return environment.getPropertyCollection(JSON_TRUSTED_NETWORKS, Collections.emptyList());
}
}
diff --git a/extensions/guacamole-auth-json/src/main/resources/guac-manifest.json b/extensions/guacamole-auth-json/src/main/resources/guac-manifest.json
index cd5d61709..7d8efd5c7 100644
--- a/extensions/guacamole-auth-json/src/main/resources/guac-manifest.json
+++ b/extensions/guacamole-auth-json/src/main/resources/guac-manifest.json
@@ -1,6 +1,6 @@
{
- "guacamoleVersion" : "1.5.5",
+ "guacamoleVersion" : "1.6.0",
"name" : "Encrypted JSON Authentication",
"namespace" : "json",
diff --git a/extensions/guacamole-auth-ldap/pom.xml b/extensions/guacamole-auth-ldap/pom.xml
index 8cb4209f1..05be82421 100644
--- a/extensions/guacamole-auth-ldap/pom.xml
+++ b/extensions/guacamole-auth-ldap/pom.xml
@@ -26,14 +26,14 @@
org.apache.guacamole
guacamole-auth-ldap
jar
- 1.5.5
+ 1.6.0
guacamole-auth-ldap
http://guacamole.apache.org/
org.apache.guacamole
extensions
- 1.5.5
+ 1.6.0
../
@@ -43,7 +43,7 @@
org.apache.guacamole
guacamole-ext
- 1.5.5
+ 1.6.0
provided
diff --git a/extensions/guacamole-auth-ldap/schema/guacConfigGroup.ldif b/extensions/guacamole-auth-ldap/schema/guacConfigGroup.ldif
index 6e3f60b25..36622e280 100644
--- a/extensions/guacamole-auth-ldap/schema/guacConfigGroup.ldif
+++ b/extensions/guacamole-auth-ldap/schema/guacConfigGroup.ldif
@@ -20,9 +20,24 @@
dn: cn=guacConfigGroup,cn=schema,cn=config
objectClass: olcSchemaConfig
cn: guacConfigGroup
-olcAttributeTypes: {0}( 1.3.6.1.4.1.38971.1.1.1 NAME 'guacConfigProtocol' SYNTAX 1.3.6.1.4.1.1466
- .115.121.1.15 )
-olcAttributeTypes: {1}( 1.3.6.1.4.1.38971.1.1.2 NAME 'guacConfigParameter' SYNTAX 1.3.6.1.4.1.146
- 6.115.121.1.15 )
-olcObjectClasses: {0}( 1.3.6.1.4.1.38971.1.2.1 NAME 'guacConfigGroup' DESC 'Guacamole config
- uration group' SUP groupOfNames MUST guacConfigProtocol MAY guacConfigParameter )
+
+olcAttributeTypes: ( 1.3.6.1.4.1.38971.1.1.1 NAME 'guacConfigProtocol'
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )
+olcAttributeTypes: ( 1.3.6.1.4.1.38971.1.1.2 NAME 'guacConfigParameter'
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )
+olcAttributeTypes: ( 1.3.6.1.4.1.38971.1.1.3 NAME 'guacConfigProxyHostname'
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )
+olcAttributeTypes: ( 1.3.6.1.4.1.38971.1.1.4 NAME 'guacConfigProxyPort'
+ SINGLE-VALUE
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )
+olcAttributeTypes: ( 1.3.6.1.4.1.38971.1.1.5 NAME 'guacConfigProxyEncryption'
+ SINGLE-VALUE
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )
+olcObjectClasses: ( 1.3.6.1.4.1.38971.1.2.1 NAME 'guacConfigGroup'
+ DESC 'Guacamole configuration group'
+ SUP groupOfNames
+ MUST guacConfigProtocol
+ MAY ( guacConfigParameter $
+ guacConfigProxyHostname $
+ guacConfigProxyPort $
+ guacConfigProxyEncryption ) )
diff --git a/extensions/guacamole-auth-ldap/schema/guacConfigGroup.schema b/extensions/guacamole-auth-ldap/schema/guacConfigGroup.schema
index 129a41b77..fb7ec433e 100644
--- a/extensions/guacamole-auth-ldap/schema/guacConfigGroup.schema
+++ b/extensions/guacamole-auth-ldap/schema/guacConfigGroup.schema
@@ -18,14 +18,28 @@
#
attributetype ( 1.3.6.1.4.1.38971.1.1.1 NAME 'guacConfigProtocol'
- SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )
attributetype ( 1.3.6.1.4.1.38971.1.1.2 NAME 'guacConfigParameter'
- SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )
+
+attributetype ( 1.3.6.1.4.1.38971.1.1.3 NAME 'guacConfigProxyHostname'
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )
+
+attributetype ( 1.3.6.1.4.1.38971.1.1.4 NAME 'guacConfigProxyPort'
+ SINGLE-VALUE
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )
+
+attributetype ( 1.3.6.1.4.1.38971.1.1.5 NAME 'guacConfigProxyEncryption'
+ SINGLE-VALUE
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )
objectClass ( 1.3.6.1.4.1.38971.1.2.1 NAME 'guacConfigGroup'
DESC 'Guacamole configuration group'
SUP groupOfNames
MUST guacConfigProtocol
- MAY guacConfigParameter )
+ MAY ( guacConfigParameter $
+ guacConfigProxyHostname $
+ guacConfigProxyPort $
+ guacConfigProxyEncryption ) )
diff --git a/extensions/guacamole-auth-ldap/src/main/java/org/apache/guacamole/auth/ldap/AuthenticationProviderService.java b/extensions/guacamole-auth-ldap/src/main/java/org/apache/guacamole/auth/ldap/AuthenticationProviderService.java
index 66adb49e9..33b811e88 100644
--- a/extensions/guacamole-auth-ldap/src/main/java/org/apache/guacamole/auth/ldap/AuthenticationProviderService.java
+++ b/extensions/guacamole-auth-ldap/src/main/java/org/apache/guacamole/auth/ldap/AuthenticationProviderService.java
@@ -401,7 +401,7 @@ public class AuthenticationProviderService {
throws GuacamoleException {
// Get attributes from configuration information
- List attrList = config.getAttributes();
+ Collection attrList = config.getAttributes();
// If there are no attributes there is no reason to search LDAP
if (attrList.isEmpty())
diff --git a/extensions/guacamole-auth-ldap/src/main/java/org/apache/guacamole/auth/ldap/ConnectedLDAPConfiguration.java b/extensions/guacamole-auth-ldap/src/main/java/org/apache/guacamole/auth/ldap/ConnectedLDAPConfiguration.java
index 493cafcb7..c41114c02 100644
--- a/extensions/guacamole-auth-ldap/src/main/java/org/apache/guacamole/auth/ldap/ConnectedLDAPConfiguration.java
+++ b/extensions/guacamole-auth-ldap/src/main/java/org/apache/guacamole/auth/ldap/ConnectedLDAPConfiguration.java
@@ -19,6 +19,7 @@
package org.apache.guacamole.auth.ldap;
+import java.util.Collection;
import java.util.List;
import org.apache.directory.api.ldap.model.filter.ExprNode;
import org.apache.directory.api.ldap.model.message.AliasDerefMode;
@@ -124,7 +125,7 @@ public class ConnectedLDAPConfiguration implements LDAPConfiguration, AutoClosea
}
@Override
- public List getUsernameAttributes() throws GuacamoleException {
+ public Collection getUsernameAttributes() throws GuacamoleException {
return config.getUsernameAttributes();
}
@@ -139,7 +140,7 @@ public class ConnectedLDAPConfiguration implements LDAPConfiguration, AutoClosea
}
@Override
- public List getGroupNameAttributes() throws GuacamoleException {
+ public Collection getGroupNameAttributes() throws GuacamoleException {
return config.getGroupNameAttributes();
}
@@ -209,7 +210,7 @@ public class ConnectedLDAPConfiguration implements LDAPConfiguration, AutoClosea
}
@Override
- public List getAttributes() throws GuacamoleException {
+ public Collection getAttributes() throws GuacamoleException {
return config.getAttributes();
}
diff --git a/extensions/guacamole-auth-ldap/src/main/java/org/apache/guacamole/auth/ldap/conf/EnvironmentLDAPConfiguration.java b/extensions/guacamole-auth-ldap/src/main/java/org/apache/guacamole/auth/ldap/conf/EnvironmentLDAPConfiguration.java
index 9fb44a1fa..5ffeb203b 100644
--- a/extensions/guacamole-auth-ldap/src/main/java/org/apache/guacamole/auth/ldap/conf/EnvironmentLDAPConfiguration.java
+++ b/extensions/guacamole-auth-ldap/src/main/java/org/apache/guacamole/auth/ldap/conf/EnvironmentLDAPConfiguration.java
@@ -19,7 +19,7 @@
package org.apache.guacamole.auth.ldap.conf;
-import java.util.List;
+import java.util.Collection;
import org.apache.directory.api.ldap.model.filter.ExprNode;
import org.apache.directory.api.ldap.model.message.AliasDerefMode;
import org.apache.directory.api.ldap.model.name.Dn;
@@ -75,8 +75,8 @@ public class EnvironmentLDAPConfiguration implements LDAPConfiguration {
}
@Override
- public List getUsernameAttributes() throws GuacamoleException {
- return environment.getProperty(
+ public Collection getUsernameAttributes() throws GuacamoleException {
+ return environment.getPropertyCollection(
LDAPGuacamoleProperties.LDAP_USERNAME_ATTRIBUTE,
DEFAULT.getUsernameAttributes()
);
@@ -98,8 +98,8 @@ public class EnvironmentLDAPConfiguration implements LDAPConfiguration {
}
@Override
- public List getGroupNameAttributes() throws GuacamoleException {
- return environment.getProperty(
+ public Collection getGroupNameAttributes() throws GuacamoleException {
+ return environment.getPropertyCollection(
LDAPGuacamoleProperties.LDAP_GROUP_NAME_ATTRIBUTE,
DEFAULT.getGroupNameAttributes()
);
@@ -210,8 +210,8 @@ public class EnvironmentLDAPConfiguration implements LDAPConfiguration {
}
@Override
- public List getAttributes() throws GuacamoleException {
- return environment.getProperty(
+ public Collection getAttributes() throws GuacamoleException {
+ return environment.getPropertyCollection(
LDAPGuacamoleProperties.LDAP_USER_ATTRIBUTES,
DEFAULT.getAttributes()
);
diff --git a/extensions/guacamole-auth-ldap/src/main/java/org/apache/guacamole/auth/ldap/conf/JacksonLDAPConfiguration.java b/extensions/guacamole-auth-ldap/src/main/java/org/apache/guacamole/auth/ldap/conf/JacksonLDAPConfiguration.java
index 01d58a3e4..bddccd871 100644
--- a/extensions/guacamole-auth-ldap/src/main/java/org/apache/guacamole/auth/ldap/conf/JacksonLDAPConfiguration.java
+++ b/extensions/guacamole-auth-ldap/src/main/java/org/apache/guacamole/auth/ldap/conf/JacksonLDAPConfiguration.java
@@ -22,6 +22,7 @@ package org.apache.guacamole.auth.ldap.conf;
import com.fasterxml.jackson.annotation.JsonFormat;
import static com.fasterxml.jackson.annotation.JsonFormat.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY;
import com.fasterxml.jackson.annotation.JsonProperty;
+import java.util.Collection;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -331,7 +332,7 @@ public class JacksonLDAPConfiguration implements LDAPConfiguration {
}
@Override
- public List getUsernameAttributes() throws GuacamoleException {
+ public Collection getUsernameAttributes() throws GuacamoleException {
return withDefault(usernameAttributes, defaultConfig::getUsernameAttributes);
}
@@ -348,7 +349,7 @@ public class JacksonLDAPConfiguration implements LDAPConfiguration {
}
@Override
- public List getGroupNameAttributes() throws GuacamoleException {
+ public Collection getGroupNameAttributes() throws GuacamoleException {
return withDefault(groupNameAttributes, defaultConfig::getGroupNameAttributes);
}
@@ -424,7 +425,7 @@ public class JacksonLDAPConfiguration implements LDAPConfiguration {
}
@Override
- public List getAttributes() throws GuacamoleException {
+ public Collection getAttributes() throws GuacamoleException {
return withDefault(userAttributes, defaultConfig::getAttributes);
}
diff --git a/extensions/guacamole-auth-ldap/src/main/java/org/apache/guacamole/auth/ldap/conf/LDAPConfiguration.java b/extensions/guacamole-auth-ldap/src/main/java/org/apache/guacamole/auth/ldap/conf/LDAPConfiguration.java
index 975631d02..e57049b26 100644
--- a/extensions/guacamole-auth-ldap/src/main/java/org/apache/guacamole/auth/ldap/conf/LDAPConfiguration.java
+++ b/extensions/guacamole-auth-ldap/src/main/java/org/apache/guacamole/auth/ldap/conf/LDAPConfiguration.java
@@ -19,6 +19,7 @@
package org.apache.guacamole.auth.ldap.conf;
+import java.util.Collection;
import java.util.List;
import org.apache.directory.api.ldap.model.filter.ExprNode;
import org.apache.directory.api.ldap.model.message.AliasDerefMode;
@@ -84,7 +85,7 @@ public interface LDAPConfiguration {
* @throws GuacamoleException
* If the username attributes cannot be retrieved.
*/
- List getUsernameAttributes() throws GuacamoleException;
+ Collection getUsernameAttributes() throws GuacamoleException;
/**
* Returns the base DN under which all Guacamole users will be stored
@@ -125,7 +126,7 @@ public interface LDAPConfiguration {
* @throws GuacamoleException
* If the group name attributes cannot be retrieved.
*/
- List getGroupNameAttributes() throws GuacamoleException;
+ Collection getGroupNameAttributes() throws GuacamoleException;
/**
* Returns the base DN under which all Guacamole role based access control
@@ -305,7 +306,7 @@ public interface LDAPConfiguration {
* If the names of the LDAP user attributes to be exposed as parameter
* tokens cannot be retrieved.
*/
- List getAttributes() throws GuacamoleException;
+ Collection getAttributes() throws GuacamoleException;
/**
* Returns the name of the LDAP attribute used to enumerate members in a
diff --git a/extensions/guacamole-auth-ldap/src/main/java/org/apache/guacamole/auth/ldap/conf/LDAPGuacamoleProperties.java b/extensions/guacamole-auth-ldap/src/main/java/org/apache/guacamole/auth/ldap/conf/LDAPGuacamoleProperties.java
index cd0b724c0..7349356b9 100644
--- a/extensions/guacamole-auth-ldap/src/main/java/org/apache/guacamole/auth/ldap/conf/LDAPGuacamoleProperties.java
+++ b/extensions/guacamole-auth-ldap/src/main/java/org/apache/guacamole/auth/ldap/conf/LDAPGuacamoleProperties.java
@@ -84,8 +84,8 @@ public class LDAPGuacamoleProperties {
* one attribute, and the concatenation of that attribute and the value of
* LDAP_USER_BASE_DN must equal the user's full DN.
*/
- public static final StringListProperty LDAP_USERNAME_ATTRIBUTE =
- new StringListProperty() {
+ public static final StringGuacamoleProperty LDAP_USERNAME_ATTRIBUTE =
+ new StringGuacamoleProperty() {
@Override
public String getName() { return "ldap-username-attribute"; }
@@ -97,8 +97,8 @@ public class LDAPGuacamoleProperties {
* attributes must be present within each Guacamole user group's record in
* the LDAP directory for that group to be visible.
*/
- public static final StringListProperty LDAP_GROUP_NAME_ATTRIBUTE =
- new StringListProperty() {
+ public static final StringGuacamoleProperty LDAP_GROUP_NAME_ATTRIBUTE =
+ new StringGuacamoleProperty() {
@Override
public String getName() { return "ldap-group-name-attribute"; }
@@ -277,8 +277,8 @@ public class LDAPGuacamoleProperties {
* Custom attribute or attributes to query from Guacamole user's record in
* the LDAP directory.
*/
- public static final StringListProperty LDAP_USER_ATTRIBUTES =
- new StringListProperty() {
+ public static final StringGuacamoleProperty LDAP_USER_ATTRIBUTES =
+ new StringGuacamoleProperty() {
@Override
public String getName() { return "ldap-user-attributes"; }
diff --git a/extensions/guacamole-auth-ldap/src/main/java/org/apache/guacamole/auth/ldap/conf/StringListProperty.java b/extensions/guacamole-auth-ldap/src/main/java/org/apache/guacamole/auth/ldap/conf/StringListProperty.java
deleted file mode 100644
index f7057e9f6..000000000
--- a/extensions/guacamole-auth-ldap/src/main/java/org/apache/guacamole/auth/ldap/conf/StringListProperty.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package org.apache.guacamole.auth.ldap.conf;
-
-import java.util.Arrays;
-import java.util.List;
-import java.util.regex.Pattern;
-import org.apache.guacamole.GuacamoleException;
-import org.apache.guacamole.properties.GuacamoleProperty;
-
-/**
- * A GuacamoleProperty whose value is a List of Strings. The string value
- * parsed to produce this list is a comma-delimited list. Duplicate values are
- * ignored, as is any whitespace following delimiters. To maintain
- * compatibility with the behavior of Java properties in general, only
- * whitespace at the beginning of each value is ignored; trailing whitespace
- * becomes part of the value.
- */
-public abstract class StringListProperty implements GuacamoleProperty> {
-
- /**
- * A pattern which matches against the delimiters between values. This is
- * currently simply a comma and any following whitespace. Parts of the
- * input string which match this pattern will not be included in the parsed
- * result.
- */
- private static final Pattern DELIMITER_PATTERN = Pattern.compile(",\\s*");
-
- @Override
- public List parseValue(String values) throws GuacamoleException {
-
- // If no property provided, return null.
- if (values == null)
- return null;
-
- // Split string into a list of individual values
- List stringValues = Arrays.asList(DELIMITER_PATTERN.split(values));
- if (stringValues.isEmpty())
- return null;
-
- return stringValues;
-
- }
-
-}
diff --git a/extensions/guacamole-auth-ldap/src/main/java/org/apache/guacamole/auth/ldap/connection/ConnectionService.java b/extensions/guacamole-auth-ldap/src/main/java/org/apache/guacamole/auth/ldap/connection/ConnectionService.java
index 9da1547ba..629b10131 100644
--- a/extensions/guacamole-auth-ldap/src/main/java/org/apache/guacamole/auth/ldap/connection/ConnectionService.java
+++ b/extensions/guacamole-auth-ldap/src/main/java/org/apache/guacamole/auth/ldap/connection/ConnectionService.java
@@ -42,7 +42,11 @@ import org.apache.guacamole.auth.ldap.ConnectedLDAPConfiguration;
import org.apache.guacamole.auth.ldap.ObjectQueryService;
import org.apache.guacamole.auth.ldap.group.UserGroupService;
import org.apache.guacamole.auth.ldap.user.LDAPAuthenticatedUser;
+import org.apache.guacamole.environment.LocalEnvironment;
+import org.apache.guacamole.net.auth.AuthenticatedUser;
import org.apache.guacamole.net.auth.Connection;
+import org.apache.guacamole.net.auth.GuacamoleProxyConfiguration;
+import org.apache.guacamole.net.auth.GuacamoleProxyConfiguration.EncryptionMethod;
import org.apache.guacamole.net.auth.TokenInjectingConnection;
import org.apache.guacamole.net.auth.simple.SimpleConnection;
import org.apache.guacamole.protocol.GuacamoleConfiguration;
@@ -59,6 +63,33 @@ public class ConnectionService {
* Logger for this class.
*/
private static final Logger logger = LoggerFactory.getLogger(ConnectionService.class);
+
+ /**
+ * The name of the LDAP attribute that stores connection configuration
+ * parameters for Guacamole.
+ */
+ public static final String LDAP_ATTRIBUTE_PARAMETER = "guacConfigParameter";
+
+ /**
+ * The name of the LDAP attribute that stores the protocol for a Guacamole
+ * connection.
+ */
+ public static final String LDAP_ATTRIBUTE_PROTOCOL = "guacConfigProtocol";
+
+ /**
+ * The name of the LDAP attribute that stores guacd proxy hostname.
+ */
+ public static final String LDAP_ATTRIBUTE_PROXY_HOSTNAME = "guacConfigProxyHostname";
+
+ /**
+ * The name of the LDAP attribute that stores guacd proxy port.
+ */
+ public static final String LDAP_ATTRIBUTE_PROXY_PORT = "guacConfigProxyPort";
+
+ /**
+ * The name of the LDAP attribute that stores guacd proxy hostname.
+ */
+ public static final String LDAP_ATTRIBUTE_PROXY_ENCRYPTION = "guacConfigProxyEncryption";
/**
* Service for executing LDAP queries.
@@ -192,11 +223,21 @@ public class ConnectionService {
config.setProtocol(protocol.getString());
}
catch (LdapInvalidAttributeValueException e) {
- logger.error("Invalid value of the protocol entry: {}",
- e.getMessage());
+ logger.error("Invalid value of the protocol entry: {}", e.getMessage());
logger.debug("LDAP exception when getting protocol value.", e);
return null;
}
+
+ // Get proxy configuration, if any
+ GuacamoleProxyConfiguration proxyConfig;
+ try {
+ proxyConfig = getProxyConfiguration(entry);
+ }
+ catch (GuacamoleException e) {
+ logger.error("Failed to retrieve proxy configuration.", e.getMessage());
+ logger.debug("Guacamole Exception when retrieving proxy configuration.", e);
+ return null;
+ }
// Get parameters, if any
Attribute parameterAttribute = entry.get(LDAP_ATTRIBUTE_NAME_PARAMETER);
@@ -209,10 +250,8 @@ public class ConnectionService {
parameter = parameterAttribute.getString();
}
catch (LdapInvalidAttributeValueException e) {
- logger.warn("Parameter value not valid for {}: {}",
- cnName, e.getMessage());
- logger.debug("LDAP exception when getting parameter value.",
- e);
+ logger.warn("Parameter value not valid for {}: {}", cnName, e.getMessage());
+ logger.debug("LDAP exception when getting parameter value.", e);
return null;
}
parameterAttribute.remove(parameter);
@@ -234,7 +273,7 @@ public class ConnectionService {
}
// Store connection using cn for both identifier and name
- Connection connection = new SimpleConnection(cnName, cnName, config, true);
+ Connection connection = new SimpleConnection(cnName, cnName, proxyConfig, config, true);
connection.setParentIdentifier(LDAPAuthenticationProvider.ROOT_CONNECTION_GROUP);
// Inject LDAP-specific tokens only if LDAP handled user
@@ -301,5 +340,64 @@ public class ConnectionService {
return searchFilter;
}
+
+ /**
+ * Given an LDAP entry that stores a GuacamoleConfiguration, generate a
+ * GuacamoleProxyConfiguration that tells the client how to connect to guacd.
+ * If the proxy configuration values are not found in the LDAP entry the
+ * defaults from the environment are used. If errors occur while trying to
+ * ready or parse values from the LDAP entry a GuacamoleException is thrown.
+ *
+ * @param connectionEntry
+ * The LDAP entry that should be checked for proxy configuration values.
+ *
+ * @return
+ * The GuacamoleProxyConfiguration that contains information on how
+ * to contact guacd for the given Guacamole connection configuration.
+ *
+ * @throws GuacamoleException
+ * If errors occur trying to parse LDAP values from the entry.
+ */
+ private GuacamoleProxyConfiguration getProxyConfiguration(Entry connectionEntry)
+ throws GuacamoleException {
+
+ try {
+
+ // Get default proxy configuration values
+ GuacamoleProxyConfiguration proxyConfig = LocalEnvironment.getInstance().getDefaultGuacamoleProxyConfiguration();
+ String proxyHostname = proxyConfig.getHostname();
+ int proxyPort = proxyConfig.getPort();
+ EncryptionMethod proxyEncryption = proxyConfig.getEncryptionMethod();
+
+ // Get the proxy hostname
+ Attribute proxyHostAttr = connectionEntry.get(LDAP_ATTRIBUTE_PROXY_HOSTNAME);
+ if (proxyHostAttr != null && proxyHostAttr.size() > 0)
+ proxyHostname = proxyHostAttr.getString();
+
+ // Get the proxy port
+ Attribute proxyPortAttr = connectionEntry.get(LDAP_ATTRIBUTE_PROXY_PORT);
+ if (proxyPortAttr != null && proxyPortAttr.size() > 0)
+ proxyPort = Integer.parseInt(proxyPortAttr.getString());
+
+ // Get the proxy encryption method
+ Attribute proxyEncryptionAttr = connectionEntry.get(LDAP_ATTRIBUTE_PROXY_ENCRYPTION);
+ if (proxyEncryptionAttr != null && proxyEncryptionAttr.size() > 0) {
+ try {
+ proxyEncryption = EncryptionMethod.valueOf(proxyEncryptionAttr.getString());
+ }
+ catch (IllegalArgumentException e) {
+ throw new GuacamoleServerException("Unknown encryption method specified, value must be either \"NONE\" or \"SSL\".", e);
+ }
+ }
+
+ // Return a new proxy configuration
+ return new GuacamoleProxyConfiguration(proxyHostname, proxyPort, proxyEncryption);
+ }
+ catch (LdapInvalidAttributeValueException e) {
+ logger.error("Invalid value in proxy configuration: {}", e.getMessage());
+ logger.debug("LDAP exception fetching proxy attribute value.", e);
+ throw new GuacamoleServerException("Invalid LDAP value in proxy configuration.", e);
+ }
+ }
}
diff --git a/extensions/guacamole-auth-ldap/src/main/java/org/apache/guacamole/auth/ldap/user/UserService.java b/extensions/guacamole-auth-ldap/src/main/java/org/apache/guacamole/auth/ldap/user/UserService.java
index fa9fe1522..38fa33e7e 100644
--- a/extensions/guacamole-auth-ldap/src/main/java/org/apache/guacamole/auth/ldap/user/UserService.java
+++ b/extensions/guacamole-auth-ldap/src/main/java/org/apache/guacamole/auth/ldap/user/UserService.java
@@ -183,7 +183,7 @@ public class UserService {
throws GuacamoleException {
// Pull username attributes from properties
- List usernameAttributes = config.getUsernameAttributes();
+ List usernameAttributes = new ArrayList<>(config.getUsernameAttributes());
// We need exactly one base DN to derive the user DN
if (usernameAttributes.size() != 1) {
diff --git a/extensions/guacamole-auth-ldap/src/main/resources/guac-manifest.json b/extensions/guacamole-auth-ldap/src/main/resources/guac-manifest.json
index d0c02721a..dc812d399 100644
--- a/extensions/guacamole-auth-ldap/src/main/resources/guac-manifest.json
+++ b/extensions/guacamole-auth-ldap/src/main/resources/guac-manifest.json
@@ -1,6 +1,6 @@
{
- "guacamoleVersion" : "1.5.5",
+ "guacamoleVersion" : "1.6.0",
"name" : "LDAP Authentication",
"namespace" : "ldap",
diff --git a/extensions/guacamole-auth-quickconnect/pom.xml b/extensions/guacamole-auth-quickconnect/pom.xml
index e72776f72..28e62310a 100644
--- a/extensions/guacamole-auth-quickconnect/pom.xml
+++ b/extensions/guacamole-auth-quickconnect/pom.xml
@@ -26,14 +26,14 @@
org.apache.guacamole
guacamole-auth-quickconnect
jar
- 1.5.5
+ 1.6.0
guacamole-auth-quickconnect
http://guacamole.apache.org/
org.apache.guacamole
extensions
- 1.5.5
+ 1.6.0
../
@@ -98,7 +98,7 @@
org.apache.guacamole
guacamole-ext
- 1.5.5
+ 1.6.0
provided
diff --git a/extensions/guacamole-auth-quickconnect/src/main/java/org/apache/guacamole/auth/quickconnect/conf/ConfigurationService.java b/extensions/guacamole-auth-quickconnect/src/main/java/org/apache/guacamole/auth/quickconnect/conf/ConfigurationService.java
index 11f11f3f8..e8e8fd34d 100644
--- a/extensions/guacamole-auth-quickconnect/src/main/java/org/apache/guacamole/auth/quickconnect/conf/ConfigurationService.java
+++ b/extensions/guacamole-auth-quickconnect/src/main/java/org/apache/guacamole/auth/quickconnect/conf/ConfigurationService.java
@@ -20,10 +20,11 @@
package org.apache.guacamole.auth.quickconnect.conf;
import com.google.inject.Inject;
+import java.util.Collection;
import java.util.List;
import org.apache.guacamole.GuacamoleException;
import org.apache.guacamole.environment.Environment;
-import org.apache.guacamole.properties.StringListProperty;
+import org.apache.guacamole.properties.StringGuacamoleProperty;
/**
* Configuration options to control the QuickConnect module.
@@ -42,7 +43,7 @@ public class ConfigurationService {
* the parameters defined in this list. Defaults to null (all parameters
* are allowed).
*/
- public static final StringListProperty QUICKCONNECT_ALLOWED_PARAMETERS = new StringListProperty() {
+ public static final StringGuacamoleProperty QUICKCONNECT_ALLOWED_PARAMETERS = new StringGuacamoleProperty() {
@Override
public String getName() { return "quickconnect-allowed-parameters"; }
@@ -55,7 +56,7 @@ public class ConfigurationService {
* except the ones defined in this list. Defaults to null (all parameters
* are allowed).
*/
- public static final StringListProperty QUICKCONNECT_DENIED_PARAMETERS = new StringListProperty() {
+ public static final StringGuacamoleProperty QUICKCONNECT_DENIED_PARAMETERS = new StringGuacamoleProperty() {
@Override
public String getName() { return "quickconnect-denied-parameters"; }
@@ -74,8 +75,8 @@ public class ConfigurationService {
* @throws GuacamoleException
* If guacamole.properties cannot be parsed.
*/
- public List getAllowedParameters() throws GuacamoleException {
- return environment.getProperty(QUICKCONNECT_ALLOWED_PARAMETERS);
+ public Collection getAllowedParameters() throws GuacamoleException {
+ return environment.getPropertyCollection(QUICKCONNECT_ALLOWED_PARAMETERS);
}
/**
@@ -90,8 +91,8 @@ public class ConfigurationService {
* @throws GuacamoleException
* If guacamole.properties cannot be parsed.
*/
- public List getDeniedParameters() throws GuacamoleException {
- return environment.getProperty(QUICKCONNECT_DENIED_PARAMETERS);
+ public Collection getDeniedParameters() throws GuacamoleException {
+ return environment.getPropertyCollection(QUICKCONNECT_DENIED_PARAMETERS);
}
}
diff --git a/extensions/guacamole-auth-quickconnect/src/main/java/org/apache/guacamole/auth/quickconnect/utility/QCParser.java b/extensions/guacamole-auth-quickconnect/src/main/java/org/apache/guacamole/auth/quickconnect/utility/QCParser.java
index 32df74297..e71988e63 100644
--- a/extensions/guacamole-auth-quickconnect/src/main/java/org/apache/guacamole/auth/quickconnect/utility/QCParser.java
+++ b/extensions/guacamole-auth-quickconnect/src/main/java/org/apache/guacamole/auth/quickconnect/utility/QCParser.java
@@ -25,6 +25,7 @@ import java.net.URI;
import java.net.URISyntaxException;
import java.net.URLDecoder;
import java.util.Arrays;
+import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.regex.Matcher;
@@ -60,13 +61,13 @@ public class QCParser {
* by this parser. If not defined, all parameters will be allowed unless
* explicitly denied.
*/
- private final List allowedParams;
+ private final Collection allowedParams;
/**
* The list of parameters that are explicitly denied from being placed into
* a configuration by this parser.
*/
- private final List deniedParams;
+ private final Collection deniedParams;
/**
* Create a new instance of the QCParser class, with the provided allowed
@@ -81,7 +82,7 @@ public class QCParser {
* A list of parameters, if any, that should be explicitly denied from
* being placed into a connection configuration.
*/
- public QCParser(List allowedParams, List deniedParams) {
+ public QCParser(Collection allowedParams, Collection deniedParams) {
this.allowedParams = allowedParams;
this.deniedParams = deniedParams;
}
diff --git a/extensions/guacamole-auth-quickconnect/src/main/resources/guac-manifest.json b/extensions/guacamole-auth-quickconnect/src/main/resources/guac-manifest.json
index 889197ca2..2225adba6 100644
--- a/extensions/guacamole-auth-quickconnect/src/main/resources/guac-manifest.json
+++ b/extensions/guacamole-auth-quickconnect/src/main/resources/guac-manifest.json
@@ -1,5 +1,5 @@
{
- "guacamoleVersion" : "1.5.5",
+ "guacamoleVersion" : "1.6.0",
"name" : "Adhoc Guacamole Connections",
"namespace" : "quickconnect",
diff --git a/extensions/guacamole-auth-radius/pom.xml b/extensions/guacamole-auth-radius/pom.xml
index d7e86fffc..b518981f1 100644
--- a/extensions/guacamole-auth-radius/pom.xml
+++ b/extensions/guacamole-auth-radius/pom.xml
@@ -26,14 +26,14 @@
org.apache.guacamole
guacamole-auth-radius
jar
- 1.5.5
+ 1.6.0
guacamole-auth-radius
http://guacamole.apache.org/
org.apache.guacamole
extensions
- 1.5.5
+ 1.6.0
../
@@ -115,7 +115,7 @@
org.apache.guacamole
guacamole-ext
- 1.5.5
+ 1.6.0
provided
diff --git a/extensions/guacamole-auth-radius/src/main/resources/guac-manifest.json b/extensions/guacamole-auth-radius/src/main/resources/guac-manifest.json
index 6b549699b..0f70eb09e 100644
--- a/extensions/guacamole-auth-radius/src/main/resources/guac-manifest.json
+++ b/extensions/guacamole-auth-radius/src/main/resources/guac-manifest.json
@@ -1,6 +1,6 @@
{
- "guacamoleVersion" : "1.5.5",
+ "guacamoleVersion" : "1.6.0",
"name" : "RADIUS Authentication Backend",
"namespace" : "radius",
diff --git a/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-base/pom.xml b/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-base/pom.xml
index d6b9a9061..1cfb1815d 100644
--- a/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-base/pom.xml
+++ b/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-base/pom.xml
@@ -32,7 +32,7 @@
org.apache.guacamole
guacamole-auth-sso
- 1.5.5
+ 1.6.0
../../
diff --git a/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-cas/pom.xml b/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-cas/pom.xml
index 7d46635f5..fc11fe6c0 100644
--- a/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-cas/pom.xml
+++ b/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-cas/pom.xml
@@ -26,14 +26,14 @@
org.apache.guacamole
guacamole-auth-sso-cas
jar
- 1.5.5
+ 1.6.0
guacamole-auth-sso-cas
http://guacamole.apache.org/
org.apache.guacamole
guacamole-auth-sso
- 1.5.5
+ 1.6.0
../../
diff --git a/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-cas/src/main/resources/guac-manifest.json b/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-cas/src/main/resources/guac-manifest.json
index db0af2c81..ed21da1b7 100644
--- a/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-cas/src/main/resources/guac-manifest.json
+++ b/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-cas/src/main/resources/guac-manifest.json
@@ -1,6 +1,6 @@
{
- "guacamoleVersion" : "1.5.5",
+ "guacamoleVersion" : "1.6.0",
"name" : "CAS Authentication Extension",
"namespace" : "cas",
diff --git a/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-dist/pom.xml b/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-dist/pom.xml
index 4ceb3810d..2c59c5614 100644
--- a/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-dist/pom.xml
+++ b/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-dist/pom.xml
@@ -32,7 +32,7 @@
org.apache.guacamole
guacamole-auth-sso
- 1.5.5
+ 1.6.0
../../
@@ -42,28 +42,28 @@
org.apache.guacamole
guacamole-auth-sso-cas
- 1.5.5
+ 1.6.0
org.apache.guacamole
guacamole-auth-sso-openid
- 1.5.5
+ 1.6.0
org.apache.guacamole
guacamole-auth-sso-saml
- 1.5.5
+ 1.6.0
org.apache.guacamole
guacamole-auth-sso-ssl
- 1.5.5
+ 1.6.0
diff --git a/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-openid/pom.xml b/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-openid/pom.xml
index f2e0c34cb..e53143485 100644
--- a/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-openid/pom.xml
+++ b/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-openid/pom.xml
@@ -26,14 +26,14 @@
org.apache.guacamole
guacamole-auth-sso-openid
jar
- 1.5.5
+ 1.6.0
guacamole-auth-sso-openid
http://guacamole.apache.org/
org.apache.guacamole
guacamole-auth-sso
- 1.5.5
+ 1.6.0
../../
diff --git a/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-openid/src/main/java/org/apache/guacamole/auth/openid/conf/ConfigurationService.java b/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-openid/src/main/java/org/apache/guacamole/auth/openid/conf/ConfigurationService.java
index bbfdea17e..444bd7706 100644
--- a/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-openid/src/main/java/org/apache/guacamole/auth/openid/conf/ConfigurationService.java
+++ b/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-openid/src/main/java/org/apache/guacamole/auth/openid/conf/ConfigurationService.java
@@ -21,13 +21,13 @@ package org.apache.guacamole.auth.openid.conf;
import com.google.inject.Inject;
import java.net.URI;
+import java.util.Collection;
import java.util.Collections;
import java.util.List;
import org.apache.guacamole.GuacamoleException;
import org.apache.guacamole.environment.Environment;
import org.apache.guacamole.properties.IntegerGuacamoleProperty;
import org.apache.guacamole.properties.StringGuacamoleProperty;
-import org.apache.guacamole.properties.StringListProperty;
import org.apache.guacamole.properties.URIGuacamoleProperty;
/**
@@ -138,8 +138,8 @@ public class ConfigurationService {
* The claims within any valid JWT that should be mapped to
* the authenticated user's tokens, as configured with guacamole.properties.
*/
- private static final StringListProperty OPENID_ATTRIBUTES_CLAIM_TYPE =
- new StringListProperty() {
+ private static final StringGuacamoleProperty OPENID_ATTRIBUTES_CLAIM_TYPE =
+ new StringGuacamoleProperty() {
@Override
public String getName() { return "openid-attributes-claim-type"; }
};
@@ -356,8 +356,8 @@ public class ConfigurationService {
* @throws GuacamoleException
* If guacamole.properties cannot be parsed.
*/
- public List getAttributesClaimType() throws GuacamoleException {
- return environment.getProperty(OPENID_ATTRIBUTES_CLAIM_TYPE, DEFAULT_ATTRIBUTES_CLAIM_TYPE);
+ public Collection getAttributesClaimType() throws GuacamoleException {
+ return environment.getPropertyCollection(OPENID_ATTRIBUTES_CLAIM_TYPE, DEFAULT_ATTRIBUTES_CLAIM_TYPE);
}
/**
diff --git a/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-openid/src/main/java/org/apache/guacamole/auth/openid/token/TokenValidationService.java b/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-openid/src/main/java/org/apache/guacamole/auth/openid/token/TokenValidationService.java
index 2fad48ce4..139ab2021 100644
--- a/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-openid/src/main/java/org/apache/guacamole/auth/openid/token/TokenValidationService.java
+++ b/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-openid/src/main/java/org/apache/guacamole/auth/openid/token/TokenValidationService.java
@@ -20,6 +20,7 @@
package org.apache.guacamole.auth.openid.token;
import com.google.inject.Inject;
+import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
@@ -229,7 +230,7 @@ public class TokenValidationService {
* If guacamole.properties could not be parsed.
*/
public Map processAttributes(JwtClaims claims) throws GuacamoleException {
- List attributesClaim = confService.getAttributesClaimType();
+ Collection attributesClaim = confService.getAttributesClaimType();
if (claims != null && !attributesClaim.isEmpty()) {
try {
diff --git a/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-openid/src/main/resources/guac-manifest.json b/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-openid/src/main/resources/guac-manifest.json
index 0f0efa95f..2bd7e2938 100644
--- a/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-openid/src/main/resources/guac-manifest.json
+++ b/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-openid/src/main/resources/guac-manifest.json
@@ -1,6 +1,6 @@
{
- "guacamoleVersion" : "1.5.5",
+ "guacamoleVersion" : "1.6.0",
"name" : "OpenID Authentication Extension",
"namespace" : "openid",
diff --git a/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-saml/pom.xml b/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-saml/pom.xml
index 2a3bc75ff..28b975aee 100644
--- a/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-saml/pom.xml
+++ b/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-saml/pom.xml
@@ -26,14 +26,14 @@
org.apache.guacamole
guacamole-auth-sso-saml
jar
- 1.5.5
+ 1.6.0
guacamole-auth-sso-saml
http://guacamole.apache.org/
org.apache.guacamole
guacamole-auth-sso
- 1.5.5
+ 1.6.0
../../
diff --git a/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-saml/src/main/resources/guac-manifest.json b/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-saml/src/main/resources/guac-manifest.json
index 2a7f452e6..593fd44c9 100644
--- a/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-saml/src/main/resources/guac-manifest.json
+++ b/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-saml/src/main/resources/guac-manifest.json
@@ -1,6 +1,6 @@
{
- "guacamoleVersion" : "1.5.5",
+ "guacamoleVersion" : "1.6.0",
"name" : "SAML Authentication Extension",
"namespace" : "saml",
diff --git a/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-ssl/pom.xml b/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-ssl/pom.xml
index acc40c185..479bfdfbd 100644
--- a/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-ssl/pom.xml
+++ b/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-ssl/pom.xml
@@ -26,14 +26,14 @@
org.apache.guacamole
guacamole-auth-sso-ssl
jar
- 1.5.5
+ 1.6.0
guacamole-auth-sso-ssl
http://guacamole.apache.org/
org.apache.guacamole
guacamole-auth-sso
- 1.5.5
+ 1.6.0
../../
diff --git a/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-ssl/src/main/java/org/apache/guacamole/auth/ssl/SSLClientAuthenticationResource.java b/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-ssl/src/main/java/org/apache/guacamole/auth/ssl/SSLClientAuthenticationResource.java
index 984a68f34..fd3230b7d 100644
--- a/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-ssl/src/main/java/org/apache/guacamole/auth/ssl/SSLClientAuthenticationResource.java
+++ b/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-ssl/src/main/java/org/apache/guacamole/auth/ssl/SSLClientAuthenticationResource.java
@@ -26,6 +26,7 @@ import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
+import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;
@@ -214,7 +215,7 @@ public class SSLClientAuthenticationResource extends SSOResource {
// Verify that the username is specified with one of the allowed
// attributes
- List usernameAttributes = confService.getSubjectUsernameAttributes();
+ Collection usernameAttributes = confService.getSubjectUsernameAttributes();
if (usernameAttributes != null && !usernameAttributes.stream().anyMatch(nameRdn.getType()::equalsIgnoreCase))
throw new GuacamoleClientException("Subject DN \"" + dn + "\" "
+ "does not contain an acceptable username attribute.");
diff --git a/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-ssl/src/main/java/org/apache/guacamole/auth/ssl/conf/ConfigurationService.java b/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-ssl/src/main/java/org/apache/guacamole/auth/ssl/conf/ConfigurationService.java
index 48fc86b65..7931c0dad 100644
--- a/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-ssl/src/main/java/org/apache/guacamole/auth/ssl/conf/ConfigurationService.java
+++ b/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-ssl/src/main/java/org/apache/guacamole/auth/ssl/conf/ConfigurationService.java
@@ -22,7 +22,7 @@ package org.apache.guacamole.auth.ssl.conf;
import com.google.inject.Inject;
import java.net.URI;
import java.net.URISyntaxException;
-import java.util.List;
+import java.util.Collection;
import javax.naming.ldap.LdapName;
import javax.ws.rs.core.UriBuilder;
import org.apache.guacamole.GuacamoleException;
@@ -30,7 +30,6 @@ import org.apache.guacamole.GuacamoleServerException;
import org.apache.guacamole.environment.Environment;
import org.apache.guacamole.properties.IntegerGuacamoleProperty;
import org.apache.guacamole.properties.StringGuacamoleProperty;
-import org.apache.guacamole.properties.StringListProperty;
import org.apache.guacamole.properties.URIGuacamoleProperty;
/**
@@ -146,8 +145,8 @@ public class ConfigurationService {
* one of these attributes, the certificate will be rejected. By default,
* any attribute is accepted.
*/
- private static final StringListProperty SSL_SUBJECT_USERNAME_ATTRIBUTE =
- new StringListProperty () {
+ private static final StringGuacamoleProperty SSL_SUBJECT_USERNAME_ATTRIBUTE =
+ new StringGuacamoleProperty () {
@Override
public String getName() { return "ssl-subject-username-attribute"; }
@@ -433,8 +432,8 @@ public class ConfigurationService {
* @throws GuacamoleException
* If the configured set of username attributes cannot be read.
*/
- public List getSubjectUsernameAttributes() throws GuacamoleException {
- return environment.getProperty(SSL_SUBJECT_USERNAME_ATTRIBUTE);
+ public Collection getSubjectUsernameAttributes() throws GuacamoleException {
+ return environment.getPropertyCollection(SSL_SUBJECT_USERNAME_ATTRIBUTE);
}
}
diff --git a/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-ssl/src/main/resources/guac-manifest.json b/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-ssl/src/main/resources/guac-manifest.json
index 7f67fc5ba..2e23e67ef 100644
--- a/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-ssl/src/main/resources/guac-manifest.json
+++ b/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-ssl/src/main/resources/guac-manifest.json
@@ -1,6 +1,6 @@
{
- "guacamoleVersion" : "1.5.5",
+ "guacamoleVersion" : "1.6.0",
"name" : "SSL Authentication Extension",
"namespace" : "ssl",
diff --git a/extensions/guacamole-auth-sso/pom.xml b/extensions/guacamole-auth-sso/pom.xml
index 5c76f3d37..f95ecd6e1 100644
--- a/extensions/guacamole-auth-sso/pom.xml
+++ b/extensions/guacamole-auth-sso/pom.xml
@@ -26,14 +26,14 @@
org.apache.guacamole
guacamole-auth-sso
pom
- 1.5.5
+ 1.6.0
guacamole-auth-sso
http://guacamole.apache.org/
org.apache.guacamole
extensions
- 1.5.5
+ 1.6.0
../
@@ -60,7 +60,7 @@
org.apache.guacamole
guacamole-ext
- 1.5.5
+ 1.6.0
provided
@@ -68,7 +68,7 @@
org.apache.guacamole
guacamole-auth-sso-base
- 1.5.5
+ 1.6.0
diff --git a/extensions/guacamole-auth-totp/pom.xml b/extensions/guacamole-auth-totp/pom.xml
index 36279940f..765667ba1 100644
--- a/extensions/guacamole-auth-totp/pom.xml
+++ b/extensions/guacamole-auth-totp/pom.xml
@@ -26,14 +26,14 @@
org.apache.guacamole
guacamole-auth-totp
jar
- 1.5.5
+ 1.6.0
guacamole-auth-totp
http://guacamole.incubator.apache.org/
org.apache.guacamole
extensions
- 1.5.5
+ 1.6.0
../
@@ -127,7 +127,7 @@
org.apache.guacamole
guacamole-ext
- 1.5.5
+ 1.6.0
provided
@@ -177,6 +177,14 @@
2.1.1
provided
+
+
+
+ com.github.seancfoley
+ ipaddress
+ 5.5.0
+ provided
+
diff --git a/extensions/guacamole-auth-totp/src/main/java/org/apache/guacamole/auth/totp/conf/ConfigurationService.java b/extensions/guacamole-auth-totp/src/main/java/org/apache/guacamole/auth/totp/conf/ConfigurationService.java
index 06984ce40..311291484 100644
--- a/extensions/guacamole-auth-totp/src/main/java/org/apache/guacamole/auth/totp/conf/ConfigurationService.java
+++ b/extensions/guacamole-auth-totp/src/main/java/org/apache/guacamole/auth/totp/conf/ConfigurationService.java
@@ -20,10 +20,14 @@
package org.apache.guacamole.auth.totp.conf;
import com.google.inject.Inject;
+import inet.ipaddr.IPAddress;
+import java.util.Collections;
+import java.util.List;
import org.apache.guacamole.GuacamoleException;
import org.apache.guacamole.GuacamoleServerException;
import org.apache.guacamole.environment.Environment;
import org.apache.guacamole.properties.EnumGuacamoleProperty;
+import org.apache.guacamole.properties.IPAddressListProperty;
import org.apache.guacamole.properties.IntegerGuacamoleProperty;
import org.apache.guacamole.properties.StringGuacamoleProperty;
import org.apache.guacamole.totp.TOTPGenerator;
@@ -88,6 +92,36 @@ public class ConfigurationService {
public String getName() { return "totp-mode"; }
};
+
+ /**
+ * A property that contains a list of IP addresses and/or subnets for which
+ * MFA via the TOTP module should be bypassed. Users logging in from addresses
+ * contained in this list will not be prompted for a second authentication
+ * factor. If this property is empty or not defined, and the TOTP module
+ * is installed, all users will be prompted for MFA.
+ */
+ private static final IPAddressListProperty TOTP_BYPASS_HOSTS =
+ new IPAddressListProperty() {
+
+ @Override
+ public String getName() { return "totp-bypass-hosts"; }
+
+ };
+
+ /**
+ * A property that contains a list of IP addresses and/or subnets for which
+ * MFA via the TOTP module should explicitly be enabled. If this property is defined,
+ * and the TOTP module is installed, users logging in from hosts contained
+ * in this list will be prompted for MFA, and users logging in from all
+ * other hosts will not be prompted for MFA.
+ */
+ private static final IPAddressListProperty TOTP_ENFORCE_HOSTS =
+ new IPAddressListProperty() {
+
+ @Override
+ public String getName() { return "totp-enforce-hosts"; }
+
+ };
/**
* Returns the human-readable name of the entity issuing user accounts. If
@@ -158,5 +192,39 @@ public class ConfigurationService {
public TOTPGenerator.Mode getMode() throws GuacamoleException {
return environment.getProperty(TOTP_MODE, TOTPGenerator.Mode.SHA1);
}
+
+ /**
+ * Return the list of IP addresses and/or subnets for which MFA authentication via the
+ * TOTP module should be bypassed, allowing users from those addresses to log in
+ * without the MFA requirement.
+ *
+ * @return
+ * A list of IP addresses and/or subnets for which MFA authentication
+ * should be bypassed.
+ *
+ * @throws GuacamoleException
+ * If guacamole.properties cannot be parsed, or an invalid IP address
+ * or subnet is specified.
+ */
+ public List getBypassHosts() throws GuacamoleException {
+ return environment.getProperty(TOTP_BYPASS_HOSTS, Collections.emptyList());
+ }
+
+ /**
+ * Return the list of IP addresses and/or subnets for which MFA authentication via the TOTP
+ * module should be explicitly enabled, requiring users logging in from hosts specified in
+ * the list to complete MFA.
+ *
+ * @return
+ * A list of IP addresses and/or subnets for which MFA authentication
+ * should be explicitly enabled.
+ *
+ * @throws GuacamoleException
+ * If guacamole.properties cannot be parsed, or an invalid IP address
+ * or subnet is specified.
+ */
+ public List getEnforceHosts() throws GuacamoleException {
+ return environment.getProperty(TOTP_ENFORCE_HOSTS, Collections.emptyList());
+ }
}
diff --git a/extensions/guacamole-auth-totp/src/main/java/org/apache/guacamole/auth/totp/user/UserVerificationService.java b/extensions/guacamole-auth-totp/src/main/java/org/apache/guacamole/auth/totp/user/UserVerificationService.java
index 30573fcbf..e08042551 100644
--- a/extensions/guacamole-auth-totp/src/main/java/org/apache/guacamole/auth/totp/user/UserVerificationService.java
+++ b/extensions/guacamole-auth-totp/src/main/java/org/apache/guacamole/auth/totp/user/UserVerificationService.java
@@ -22,9 +22,12 @@ package org.apache.guacamole.auth.totp.user;
import com.google.common.io.BaseEncoding;
import com.google.inject.Inject;
import com.google.inject.Provider;
+import inet.ipaddr.IPAddress;
+import inet.ipaddr.IPAddressString;
import java.security.InvalidKeyException;
import java.util.Collections;
import java.util.HashMap;
+import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.servlet.http.HttpServletRequest;
@@ -44,6 +47,7 @@ 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.credentials.CredentialsInfo;
+import org.apache.guacamole.properties.IPAddressListProperty;
import org.apache.guacamole.totp.TOTPGenerator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -311,6 +315,45 @@ public class UserVerificationService {
public void verifyIdentity(UserContext context,
AuthenticatedUser authenticatedUser) throws GuacamoleException {
+ // Pull the original HTTP request used to authenticate
+ Credentials credentials = authenticatedUser.getCredentials();
+ HttpServletRequest request = credentials.getRequest();
+
+ // Get the current client address
+ IPAddress clientAddr = new IPAddressString(request.getRemoteAddr()).getAddress();
+
+ // Ignore anonymous users
+ if (authenticatedUser.getIdentifier().equals(AuthenticatedUser.ANONYMOUS_IDENTIFIER))
+ return;
+
+ // Pull address lists to check from configuration. Note that the enforce
+ // list will override the bypass list, which means that, if the client
+ // address happens to be in both lists, Duo MFA will be enforced.
+ List bypassAddresses = confService.getBypassHosts();
+ List enforceAddresses = confService.getEnforceHosts();
+
+ // Check the bypass list for the client address, and set the enforce
+ // flag to the opposite.
+ boolean enforceHost = !(IPAddressListProperty.addressListContains(bypassAddresses, clientAddr));
+
+ // Only continue processing if the list is not empty
+ if (!enforceAddresses.isEmpty()) {
+
+ // If client address is not available or invalid, MFA will
+ // be enforced.
+ if (clientAddr == null || !clientAddr.isIPAddress())
+ enforceHost = true;
+
+ // Check the enforce list and set the flag if the client address
+ // is found in the list.
+ else
+ enforceHost = IPAddressListProperty.addressListContains(enforceAddresses, clientAddr);
+ }
+
+ // If the enforce flag is not true, bypass TOTP MFA.
+ if (!enforceHost)
+ return;
+
// Ignore anonymous users
String username = authenticatedUser.getIdentifier();
if (username.equals(AuthenticatedUser.ANONYMOUS_IDENTIFIER))
@@ -325,10 +368,6 @@ public class UserVerificationService {
if (key == null)
return;
- // Pull the original HTTP request used to authenticate
- Credentials credentials = authenticatedUser.getCredentials();
- HttpServletRequest request = credentials.getRequest();
-
// Retrieve TOTP from request
String code = request.getParameter(AuthenticationCodeField.PARAMETER_NAME);
diff --git a/extensions/guacamole-auth-totp/src/main/resources/guac-manifest.json b/extensions/guacamole-auth-totp/src/main/resources/guac-manifest.json
index d0cbf15bf..8c145c4df 100644
--- a/extensions/guacamole-auth-totp/src/main/resources/guac-manifest.json
+++ b/extensions/guacamole-auth-totp/src/main/resources/guac-manifest.json
@@ -1,6 +1,6 @@
{
- "guacamoleVersion" : "1.5.5",
+ "guacamoleVersion" : "1.6.0",
"name" : "TOTP TFA Authentication Backend",
"namespace" : "totp",
diff --git a/extensions/guacamole-display-statistics/pom.xml b/extensions/guacamole-display-statistics/pom.xml
index 5c250f69c..de4995256 100644
--- a/extensions/guacamole-display-statistics/pom.xml
+++ b/extensions/guacamole-display-statistics/pom.xml
@@ -26,14 +26,14 @@
org.apache.guacamole
guacamole-display-statistics
jar
- 1.5.5
+ 1.6.0
guacamole-display-statistics
http://guacamole.apache.org/
org.apache.guacamole
extensions
- 1.5.5
+ 1.6.0
../
diff --git a/extensions/guacamole-display-statistics/src/main/resources/guac-manifest.json b/extensions/guacamole-display-statistics/src/main/resources/guac-manifest.json
index 4823dbf77..ca398dc89 100644
--- a/extensions/guacamole-display-statistics/src/main/resources/guac-manifest.json
+++ b/extensions/guacamole-display-statistics/src/main/resources/guac-manifest.json
@@ -1,6 +1,6 @@
{
- "guacamoleVersion" : "1.5.5",
+ "guacamoleVersion" : "1.6.0",
"name" : "Display Statistic Toolbar",
"namespace" : "display-stats",
diff --git a/extensions/guacamole-history-recording-storage/pom.xml b/extensions/guacamole-history-recording-storage/pom.xml
index a65190f06..1d4fbf421 100644
--- a/extensions/guacamole-history-recording-storage/pom.xml
+++ b/extensions/guacamole-history-recording-storage/pom.xml
@@ -26,14 +26,14 @@
org.apache.guacamole
guacamole-history-recording-storage
jar
- 1.5.5
+ 1.6.0
guacamole-history-recording-storage
http://guacamole.apache.org/
org.apache.guacamole
extensions
- 1.5.5
+ 1.6.0
../
@@ -43,7 +43,7 @@
org.apache.guacamole
guacamole-ext
- 1.5.5
+ 1.6.0
provided
diff --git a/extensions/guacamole-history-recording-storage/src/main/resources/guac-manifest.json b/extensions/guacamole-history-recording-storage/src/main/resources/guac-manifest.json
index 7b3fe622e..097b344e0 100644
--- a/extensions/guacamole-history-recording-storage/src/main/resources/guac-manifest.json
+++ b/extensions/guacamole-history-recording-storage/src/main/resources/guac-manifest.json
@@ -1,6 +1,6 @@
{
- "guacamoleVersion" : "1.5.5",
+ "guacamoleVersion" : "1.6.0",
"name" : "Session Recording Storage",
"namespace" : "recording-storage",
diff --git a/extensions/guacamole-vault/modules/guacamole-vault-base/pom.xml b/extensions/guacamole-vault/modules/guacamole-vault-base/pom.xml
index bdc503562..6928f5791 100644
--- a/extensions/guacamole-vault/modules/guacamole-vault-base/pom.xml
+++ b/extensions/guacamole-vault/modules/guacamole-vault-base/pom.xml
@@ -36,7 +36,7 @@
org.apache.guacamole
guacamole-vault
- 1.5.5
+ 1.6.0
../../
diff --git a/extensions/guacamole-vault/modules/guacamole-vault-dist/pom.xml b/extensions/guacamole-vault/modules/guacamole-vault-dist/pom.xml
index 6ce906c00..4c4a5184b 100644
--- a/extensions/guacamole-vault/modules/guacamole-vault-dist/pom.xml
+++ b/extensions/guacamole-vault/modules/guacamole-vault-dist/pom.xml
@@ -36,7 +36,7 @@
org.apache.guacamole
guacamole-vault
- 1.5.5
+ 1.6.0
../../
@@ -46,7 +46,7 @@
org.apache.guacamole
guacamole-vault-ksm
- 1.5.5
+ 1.6.0
diff --git a/extensions/guacamole-vault/modules/guacamole-vault-ksm/pom.xml b/extensions/guacamole-vault/modules/guacamole-vault-ksm/pom.xml
index d1828b86c..cd2ade991 100644
--- a/extensions/guacamole-vault/modules/guacamole-vault-ksm/pom.xml
+++ b/extensions/guacamole-vault/modules/guacamole-vault-ksm/pom.xml
@@ -26,14 +26,14 @@
org.apache.guacamole
guacamole-vault-ksm
jar
- 1.5.5
+ 1.6.0
guacamole-vault-ksm
http://guacamole.apache.org/
org.apache.guacamole
guacamole-vault
- 1.5.5
+ 1.6.0
../../
@@ -54,7 +54,7 @@
org.apache.guacamole
guacamole-vault-base
- 1.5.5
+ 1.6.0
diff --git a/extensions/guacamole-vault/modules/guacamole-vault-ksm/src/main/resources/guac-manifest.json b/extensions/guacamole-vault/modules/guacamole-vault-ksm/src/main/resources/guac-manifest.json
index aadd43a5b..af4e4f3cd 100644
--- a/extensions/guacamole-vault/modules/guacamole-vault-ksm/src/main/resources/guac-manifest.json
+++ b/extensions/guacamole-vault/modules/guacamole-vault-ksm/src/main/resources/guac-manifest.json
@@ -1,6 +1,6 @@
{
- "guacamoleVersion" : "1.5.5",
+ "guacamoleVersion" : "1.6.0",
"name" : "Keeper Secrets Manager",
"namespace" : "keeper-secrets-manager",
diff --git a/extensions/guacamole-vault/pom.xml b/extensions/guacamole-vault/pom.xml
index 05e1b8837..a8ea92c68 100644
--- a/extensions/guacamole-vault/pom.xml
+++ b/extensions/guacamole-vault/pom.xml
@@ -26,14 +26,14 @@
org.apache.guacamole
guacamole-vault
pom
- 1.5.5
+ 1.6.0
guacamole-vault
http://guacamole.apache.org/
org.apache.guacamole
extensions
- 1.5.5
+ 1.6.0
../
@@ -57,7 +57,7 @@
org.apache.guacamole
guacamole-ext
- 1.5.5
+ 1.6.0
provided
diff --git a/extensions/pom.xml b/extensions/pom.xml
index 2e8fca026..760c845b0 100644
--- a/extensions/pom.xml
+++ b/extensions/pom.xml
@@ -26,14 +26,14 @@
org.apache.guacamole
extensions
pom
- 1.5.5
+ 1.6.0
extensions
http://guacamole.apache.org/
org.apache.guacamole
guacamole-client
- 1.5.5
+ 1.6.0
../
diff --git a/guacamole-common-js/pom.xml b/guacamole-common-js/pom.xml
index ff1b20188..8a34eec0c 100644
--- a/guacamole-common-js/pom.xml
+++ b/guacamole-common-js/pom.xml
@@ -26,14 +26,14 @@
org.apache.guacamole
guacamole-common-js
pom
- 1.5.5
+ 1.6.0
guacamole-common-js
http://guacamole.apache.org/
org.apache.guacamole
guacamole-client
- 1.5.5
+ 1.6.0
../
diff --git a/guacamole-common-js/src/main/webapp/modules/Version.js b/guacamole-common-js/src/main/webapp/modules/Version.js
index 8a0736347..3dfb5378b 100644
--- a/guacamole-common-js/src/main/webapp/modules/Version.js
+++ b/guacamole-common-js/src/main/webapp/modules/Version.js
@@ -27,4 +27,4 @@ var Guacamole = Guacamole || {};
*
* @type {!string}
*/
-Guacamole.API_VERSION = "1.5.4";
+Guacamole.API_VERSION = "1.6.0";
diff --git a/guacamole-common/pom.xml b/guacamole-common/pom.xml
index 492960567..6f42bcc34 100644
--- a/guacamole-common/pom.xml
+++ b/guacamole-common/pom.xml
@@ -26,14 +26,14 @@
org.apache.guacamole
guacamole-common
jar
- 1.5.5
+ 1.6.0
guacamole-common
http://guacamole.apache.org/
org.apache.guacamole
guacamole-client
- 1.5.5
+ 1.6.0
../
diff --git a/guacamole-ext/pom.xml b/guacamole-ext/pom.xml
index 161fbe648..d903a9b49 100644
--- a/guacamole-ext/pom.xml
+++ b/guacamole-ext/pom.xml
@@ -26,14 +26,14 @@
org.apache.guacamole
guacamole-ext
jar
- 1.5.5
+ 1.6.0
guacamole-ext
http://guacamole.apache.org/
org.apache.guacamole
guacamole-client
- 1.5.5
+ 1.6.0
../
@@ -87,7 +87,7 @@
org.apache.guacamole
guacamole-common
- 1.5.5
+ 1.6.0
compile
@@ -110,6 +110,13 @@
jackson-databind
+
+
+ com.github.seancfoley
+ ipaddress
+ 5.5.0
+
+
diff --git a/guacamole-ext/src/main/java/org/apache/guacamole/environment/DelegatingEnvironment.java b/guacamole-ext/src/main/java/org/apache/guacamole/environment/DelegatingEnvironment.java
index cdaa924ea..936612a21 100644
--- a/guacamole-ext/src/main/java/org/apache/guacamole/environment/DelegatingEnvironment.java
+++ b/guacamole-ext/src/main/java/org/apache/guacamole/environment/DelegatingEnvironment.java
@@ -20,6 +20,7 @@
package org.apache.guacamole.environment;
import java.io.File;
+import java.util.Collection;
import java.util.Map;
import org.apache.guacamole.GuacamoleException;
import org.apache.guacamole.net.auth.GuacamoleProxyConfiguration;
@@ -73,11 +74,35 @@ public class DelegatingEnvironment implements Environment {
public Type getProperty(GuacamoleProperty property, Type defaultValue) throws GuacamoleException {
return environment.getProperty(property, defaultValue);
}
+
+ @Override
+ public Collection getPropertyCollection(GuacamoleProperty property)
+ throws GuacamoleException {
+ return environment.getPropertyCollection(property);
+ }
+
+ @Override
+ public Collection getPropertyCollection(GuacamoleProperty property,
+ Type defaultValue) throws GuacamoleException {
+ return environment.getPropertyCollection(property, defaultValue);
+ }
+
+ @Override
+ public Collection getPropertyCollection(GuacamoleProperty property,
+ Collection defaultValue) throws GuacamoleException {
+ return environment.getPropertyCollection(property, defaultValue);
+ }
@Override
public Type getRequiredProperty(GuacamoleProperty property) throws GuacamoleException {
return environment.getRequiredProperty(property);
}
+
+ @Override
+ public Collection getRequiredPropertyCollection(GuacamoleProperty property)
+ throws GuacamoleException {
+ return environment.getRequiredPropertyCollection(property);
+ }
@Override
public GuacamoleProxyConfiguration getDefaultGuacamoleProxyConfiguration() throws GuacamoleException {
diff --git a/guacamole-ext/src/main/java/org/apache/guacamole/environment/Environment.java b/guacamole-ext/src/main/java/org/apache/guacamole/environment/Environment.java
index c36b953ac..22b95149b 100644
--- a/guacamole-ext/src/main/java/org/apache/guacamole/environment/Environment.java
+++ b/guacamole-ext/src/main/java/org/apache/guacamole/environment/Environment.java
@@ -21,6 +21,8 @@ package org.apache.guacamole.environment;
import org.apache.guacamole.properties.GuacamoleProperties;
import java.io.File;
+import java.util.Collection;
+import java.util.Collections;
import java.util.Map;
import org.apache.guacamole.GuacamoleException;
import org.apache.guacamole.GuacamoleUnsupportedException;
@@ -102,13 +104,18 @@ public interface Environment {
* Given a GuacamoleProperty, parses and returns the value set for that
* property in guacamole.properties, if any.
*
- * @param The type that the given property is parsed into.
- * @param property The property to read from guacamole.properties.
- * @return The parsed value of the property as read from
- * guacamole.properties.
- * @throws GuacamoleException If an error occurs while parsing the value
- * for the given property in
- * guacamole.properties.
+ * @param
+ * The type that the given property is parsed into.
+ *
+ * @param property
+ * The property to read from guacamole.properties.
+ *
+ * @return
+ * The parsed value of the property as read from guacamole.properties.
+ *
+ * @throws GuacamoleException
+ * If an error occurs while parsing the value for the given property in
+ * guacamole.properties.
*/
public Type getProperty(GuacamoleProperty property)
throws GuacamoleException;
@@ -118,20 +125,161 @@ public interface Environment {
* property in guacamole.properties, if any. If no value is found, the
* provided default value is returned.
*
- * @param The type that the given property is parsed into.
- * @param property The property to read from guacamole.properties.
- * @param defaultValue The value to return if no value was given in
- * guacamole.properties.
- * @return The parsed value of the property as read from
- * guacamole.properties, or the provided default value if no value
- * was found.
- * @throws GuacamoleException If an error occurs while parsing the value
- * for the given property in
- * guacamole.properties.
+ * @param
+ * The type that the given property is parsed into.
+ *
+ * @param property
+ * The property to read from guacamole.properties.
+ *
+ * @param defaultValue
+ * The value to return if no value was given in guacamole.properties.
+ *
+ * @return
+ * The parsed value of the property as read from guacamole.properties,
+ * or the provided default value if no value was found.
+ *
+ * @throws GuacamoleException
+ * If an error occurs while parsing the value for the given property in
+ * guacamole.properties.
*/
public Type getProperty(GuacamoleProperty property,
Type defaultValue) throws GuacamoleException;
+ /**
+ * Given a GuacamoleProperty, parses and returns a sorted Collection of the
+ * value set for that property in guacamole.properties, if any. The
+ * implementation of parsing and returning a collection of multiple
+ * values is up to the individual property implementations, and not all
+ * implementations will support reading and returning multiple values.
+ *
+ * @param
+ * The type that the given property is parsed into.
+ *
+ * @param property
+ * The property to read from guacamole.properties.
+ *
+ * @return
+ * A sorted collection of the the parsed values of the property as read
+ * from guacamole.properties.
+ *
+ * @throws GuacamoleException
+ * If an error occurs while parsing the value for the given property in
+ * guacamole.properties.
+ */
+ public default Collection getPropertyCollection(
+ GuacamoleProperty property) throws GuacamoleException {
+
+ /* Pull the given property as a string. */
+ StringGuacamoleProperty stringProperty = new StringGuacamoleProperty() {
+
+ @Override
+ public String getName() { return property.getName(); }
+
+ };
+
+ /* Parse the string to a Collection of the desired type. */
+ return property.parseValueCollection(getProperty(stringProperty));
+
+ }
+
+ /**
+ * Given a GuacamoleProperty, parses and returns the value set for that
+ * property in guacamole.properties, if any. If no value is found, a
+ * Collection is returned with the provided default value. The
+ * implementation of parsing and returning a collection of multiple
+ * values is up to the individual property implementations, and not all
+ * implementations will support reading and returning multiple values.
+ *
+ * @param
+ * The type that the given property is parsed into.
+ *
+ * @param property
+ * The property to read from guacamole.properties.
+ *
+ * @param defaultValue
+ * The single value to return in the Collection if no value was given
+ * in guacamole.properties.
+ *
+ * @return
+ * A sorted collection of the the parsed values of the property as read
+ * from guacamole.properties, or a Collection with the single default
+ * value provided.
+ *
+ * @throws GuacamoleException
+ * If an error occurs while parsing the value for the given property in
+ * guacamole.properties.
+ */
+ public default Collection getPropertyCollection(
+ GuacamoleProperty property, Type defaultValue)
+ throws GuacamoleException {
+
+ /* Pull the given property as a string. */
+ StringGuacamoleProperty stringProperty = new StringGuacamoleProperty() {
+
+ @Override
+ public String getName() { return property.getName(); }
+
+ };
+
+ /* Check the value and return the default if null. */
+ String stringValue = getProperty(stringProperty);
+ if (stringValue == null)
+ return Collections.singletonList(defaultValue);
+
+ /* Parse the string and return the collection. */
+ return property.parseValueCollection(stringValue);
+
+ }
+
+ /**
+ * Given a GuacamoleProperty, parses and returns the value set for that
+ * property in guacamole.properties, if any. If no value is found, the
+ * provided Collection of default values is returned. The
+ * implementation of parsing and returning a collection of multiple
+ * values is up to the individual property implementations, and not all
+ * implementations will support reading and returning multiple values.
+ *
+ * @param
+ * The type that the given property is parsed into.
+ *
+ * @param property
+ * The property to read from guacamole.properties.
+ *
+ * @param defaultValue
+ * The Collection of values to return in the Collection if no value was
+ * given in guacamole.properties.
+ *
+ * @return
+ * A sorted collection of the the parsed values of the property as read
+ * from guacamole.properties, or a Collection with the single default
+ * value provided.
+ *
+ * @throws GuacamoleException
+ * If an error occurs while parsing the value for the given property in
+ * guacamole.properties.
+ */
+ public default Collection getPropertyCollection(
+ GuacamoleProperty property, Collection defaultValue)
+ throws GuacamoleException {
+
+ /* Pull the given property as a string. */
+ StringGuacamoleProperty stringProperty = new StringGuacamoleProperty() {
+
+ @Override
+ public String getName() { return property.getName(); }
+
+ };
+
+ /* Check the value and return the default if null. */
+ String stringValue = getProperty(stringProperty);
+ if (stringValue == null)
+ return defaultValue;
+
+ /* Parse the string and return the collection. */
+ return property.parseValueCollection(stringValue);
+
+ }
+
/**
* Given a GuacamoleProperty, parses and returns the value set for that
* property in guacamole.properties. An exception is thrown if the value
@@ -148,6 +296,43 @@ public interface Environment {
*/
public Type getRequiredProperty(GuacamoleProperty property)
throws GuacamoleException;
+
+ /**
+ * Given a GuacamoleProperty, parses and returns a sorted Collection of
+ * values for that property in guacamole.properties. An exception is thrown
+ * if the value is not provided. The implementation of parsing and returning
+ * a collection of multiple values is up to the individual property
+ * implementations, and not all implementations will support reading and
+ * returning multiple values.
+ *
+ * @param
+ * The type that the given property is parsed into.
+ *
+ * @param property
+ * The property to read from guacamole.properties.
+ *
+ * @return
+ * A sorted Collection of the property as read from guacamole.properties.
+ *
+ * @throws GuacamoleException
+ * If an error occurs while parsing the value for the given property in
+ * guacamole.properties, or if the property is not specified.
+ */
+ public default Collection getRequiredPropertyCollection(
+ GuacamoleProperty property) throws GuacamoleException {
+
+ /* Pull the given property as a string. */
+ StringGuacamoleProperty stringProperty = new StringGuacamoleProperty() {
+
+ @Override
+ public String getName() { return property.getName(); }
+
+ };
+
+ /* Parse the string to a Collection of the desired type. */
+ return property.parseValueCollection(getRequiredProperty(stringProperty));
+
+ }
/**
* Returns the connection information which should be used, by default, to
diff --git a/guacamole-ext/src/main/java/org/apache/guacamole/environment/LocalEnvironment.java b/guacamole-ext/src/main/java/org/apache/guacamole/environment/LocalEnvironment.java
index caf1c418e..bd0f3f152 100644
--- a/guacamole-ext/src/main/java/org/apache/guacamole/environment/LocalEnvironment.java
+++ b/guacamole-ext/src/main/java/org/apache/guacamole/environment/LocalEnvironment.java
@@ -25,6 +25,8 @@ import java.io.FileInputStream;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.InputStream;
+import java.util.Collection;
+import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -353,6 +355,38 @@ public class LocalEnvironment implements Environment {
return value;
}
+
+ @Override
+ public Collection getPropertyCollection(GuacamoleProperty property)
+ throws GuacamoleException {
+
+ return property.parseValueCollection(getPropertyValue(property.getName()));
+
+ }
+
+ @Override
+ public Collection getPropertyCollection(GuacamoleProperty property,
+ Type defaultValue) throws GuacamoleException {
+
+ Collection value = getPropertyCollection(property);
+ if (value == null)
+ return Collections.singletonList(defaultValue);
+
+ return value;
+
+ }
+
+ @Override
+ public Collection getPropertyCollection(GuacamoleProperty property,
+ Collection defaultValue) throws GuacamoleException {
+
+ Collection value = getPropertyCollection(property);
+ if (value == null)
+ return defaultValue;
+
+ return value;
+
+ }
@Override
public Type getRequiredProperty(GuacamoleProperty property)
@@ -365,6 +399,18 @@ public class LocalEnvironment implements Environment {
return value;
}
+
+ @Override
+ public Collection getRequiredPropertyCollection(GuacamoleProperty property)
+ throws GuacamoleException {
+
+ Collection value = getPropertyCollection(property);
+ if (value == null)
+ throw new GuacamoleServerException("Property " + property.getName() + " is required.");
+
+ return value;
+
+ }
@Override
public Map getProtocols() {
diff --git a/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/permission/SystemPermission.java b/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/permission/SystemPermission.java
index 054caf066..c0c17345f 100644
--- a/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/permission/SystemPermission.java
+++ b/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/permission/SystemPermission.java
@@ -56,6 +56,14 @@ public class SystemPermission implements Permission {
* Create sharing profiles.
*/
CREATE_SHARING_PROFILE,
+
+ /**
+ * Audit the system in general, which involves the ability to view
+ * active and historical connection records, user logon records, etc.,
+ * but lacks permission to change any of these details (interact with
+ * active connections, update user accounts, etc).
+ */
+ AUDIT,
/**
* Administer the system in general, including adding permissions
diff --git a/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/simple/SimpleConnection.java b/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/simple/SimpleConnection.java
index aa7e74853..8e59c3c59 100644
--- a/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/simple/SimpleConnection.java
+++ b/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/simple/SimpleConnection.java
@@ -24,7 +24,6 @@ import java.util.Date;
import java.util.Map;
import org.apache.guacamole.GuacamoleException;
import org.apache.guacamole.GuacamoleServerException;
-import org.apache.guacamole.environment.Environment;
import org.apache.guacamole.environment.LocalEnvironment;
import org.apache.guacamole.net.GuacamoleSocket;
import org.apache.guacamole.net.GuacamoleTunnel;
@@ -53,6 +52,11 @@ public class SimpleConnection extends AbstractConnection {
* Backing configuration, containing all sensitive information.
*/
private GuacamoleConfiguration fullConfig;
+
+ /**
+ * The proxy configuration describing how to connect to guacd.
+ */
+ private GuacamoleProxyConfiguration proxyConfig;
/**
* Whether parameter tokens in the underlying GuacamoleConfiguration should
@@ -158,6 +162,39 @@ public class SimpleConnection extends AbstractConnection {
this.interpretTokens = interpretTokens;
}
+
+ /**
+ * Creates a new SimpleConnection having the given identifier,
+ * GuacamoleConfiguration, and GuacamoleProxyConfiguration. Parameter tokens
+ * will be interpreted if explicitly requested.
+ *
+ * @param name
+ * The name to associate with this connection.
+ *
+ * @param identifier
+ * The identifier to associate with this connection.
+ *
+ * @param proxyConfig
+ * The Guacamole proxy configuration describing how the connection to
+ * guacd should be established, or null if the default settings will be
+ * used.
+ *
+ * @param config
+ * The configuration describing how to connect to this connection.
+ *
+ * @param interpretTokens
+ * Whether parameter tokens in the underlying GuacamoleConfiguration
+ * should be automatically applied upon connecting. If false, parameter
+ * tokens will not be interpreted at all.
+ */
+ public SimpleConnection(String name, String identifier,
+ GuacamoleProxyConfiguration proxyConfig,
+ GuacamoleConfiguration config, boolean interpretTokens) {
+
+ this(name, identifier, config, interpretTokens);
+ this.proxyConfig = proxyConfig;
+
+ }
/**
* Returns the GuacamoleConfiguration describing how to connect to this
@@ -201,9 +238,9 @@ public class SimpleConnection extends AbstractConnection {
public GuacamoleTunnel connect(GuacamoleClientInformation info)
throws GuacamoleException {
- // Retrieve proxy configuration from environment
- Environment environment = LocalEnvironment.getInstance();
- GuacamoleProxyConfiguration proxyConfig = environment.getDefaultGuacamoleProxyConfiguration();
+ // Retrieve proxy configuration from environment if we don't have one
+ if (proxyConfig == null)
+ proxyConfig = LocalEnvironment.getInstance().getDefaultGuacamoleProxyConfiguration();
// Get guacd connection parameters
String hostname = proxyConfig.getHostname();
diff --git a/guacamole-ext/src/main/java/org/apache/guacamole/properties/FileGuacamoleProperty.java b/guacamole-ext/src/main/java/org/apache/guacamole/properties/FileGuacamoleProperty.java
index ec380defb..38e1dac99 100644
--- a/guacamole-ext/src/main/java/org/apache/guacamole/properties/FileGuacamoleProperty.java
+++ b/guacamole-ext/src/main/java/org/apache/guacamole/properties/FileGuacamoleProperty.java
@@ -20,6 +20,9 @@
package org.apache.guacamole.properties;
import java.io.File;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
import org.apache.guacamole.GuacamoleException;
/**
@@ -37,5 +40,27 @@ public abstract class FileGuacamoleProperty implements GuacamoleProperty {
return new File(value);
}
+
+ @Override
+ public List parseValueCollection(String value) throws GuacamoleException {
+
+ // If no property is provided, return null.
+ if (value == null)
+ return null;
+
+ // Split string into a list of individual values
+ List stringValues = Arrays.asList(DELIMITER_PATTERN.split(value));
+ if (stringValues.isEmpty())
+ return null;
+
+ // Translate values to Files and add to result array.
+ List fileValues = new ArrayList<>();
+ for (String stringFile : stringValues) {
+ fileValues.add(new File(stringFile));
+ }
+
+ return fileValues;
+
+ }
}
diff --git a/guacamole-ext/src/main/java/org/apache/guacamole/properties/GuacamoleProperty.java b/guacamole-ext/src/main/java/org/apache/guacamole/properties/GuacamoleProperty.java
index ed0c9f1a1..bcbea055b 100644
--- a/guacamole-ext/src/main/java/org/apache/guacamole/properties/GuacamoleProperty.java
+++ b/guacamole-ext/src/main/java/org/apache/guacamole/properties/GuacamoleProperty.java
@@ -19,6 +19,9 @@
package org.apache.guacamole.properties;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.regex.Pattern;
import org.apache.guacamole.GuacamoleException;
/**
@@ -30,12 +33,21 @@ import org.apache.guacamole.GuacamoleException;
*/
public interface GuacamoleProperty {
+ /**
+ * A pattern which matches against the delimiters between values. This is
+ * currently simply a semicolon and any following whitespace. Parts of the
+ * input string which match this pattern will not be included in the parsed
+ * result.
+ */
+ static final Pattern DELIMITER_PATTERN = Pattern.compile(";\\s*");
+
/**
* Returns the name of the property in guacamole.properties that this
* GuacamoleProperty will parse.
*
- * @return The name of the property in guacamole.properties that this
- * GuacamoleProperty will parse.
+ * @return
+ * The name of the property in guacamole.properties that this
+ * GuacamoleProperty will parse.
*/
public String getName();
@@ -43,11 +55,37 @@ public interface GuacamoleProperty {
* Parses the given string value into the type associated with this
* GuacamoleProperty.
*
- * @param value The string value to parse.
- * @return The parsed value.
- * @throws GuacamoleException If an error occurs while parsing the
- * provided value.
+ * @param value
+ * The string value to parse.
+ *
+ * @return
+ * The parsed value.
+ *
+ * @throws GuacamoleException
+ * If an error occurs while parsing the provided value.
*/
public Type parseValue(String value) throws GuacamoleException;
+
+ /**
+ * Parses the given string value into a Collection of values of the type
+ * associated with this GuacamoleProperty. The default implementation
+ * simply returns a list containing a single item as parsed by the
+ * parseValue method.
+ *
+ * @param value
+ * The string value to parse.
+ *
+ * @return
+ * A sorted Collection of the parsed values.
+ *
+ * @throws GuacamoleException
+ * If an error occurs while parsing the provided value.
+ */
+ default public Collection parseValueCollection(String value)
+ throws GuacamoleException {
+
+ return Collections.singletonList(parseValue(value));
+
+ }
}
diff --git a/guacamole-ext/src/main/java/org/apache/guacamole/properties/IPAddressListProperty.java b/guacamole-ext/src/main/java/org/apache/guacamole/properties/IPAddressListProperty.java
new file mode 100644
index 000000000..1e0f6edfa
--- /dev/null
+++ b/guacamole-ext/src/main/java/org/apache/guacamole/properties/IPAddressListProperty.java
@@ -0,0 +1,113 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.guacamole.properties;
+
+import inet.ipaddr.IPAddress;
+import inet.ipaddr.IPAddressString;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.regex.Pattern;
+import org.apache.guacamole.GuacamoleException;
+import org.apache.guacamole.GuacamoleServerException;
+
+/**
+ * A GuacamoleProperty implementation that parses a String for a comma-separated
+ * list of IP addresses and/or IP subnets, both IPv4 and IPv6, and returns the
+ * list of those valid IP addresses/subnets.
+ */
+public abstract class IPAddressListProperty implements GuacamoleProperty> {
+
+ /**
+ * A pattern which matches against the delimiters between values. This is
+ * currently simply a comma and any following whitespace. Parts of the
+ * input string which match this pattern will not be included in the parsed
+ * result.
+ */
+ private static final Pattern DELIMITER_PATTERN = Pattern.compile(",\\s*");
+
+ @Override
+ public List parseValue(String values) throws GuacamoleException {
+
+ // Null for null
+ if (values == null)
+ return null;
+
+ // Not null, just empty
+ if (values.isEmpty())
+ return Collections.emptyList();
+
+ // Split the string into an array
+ List addrStrings = Arrays.asList(DELIMITER_PATTERN.split(values));
+ List ipAddresses = new ArrayList<>();
+
+ // Loop through each string
+ for (String addrString : addrStrings) {
+
+ // Convert the string to an IPAddressString for validation
+ IPAddressString ipString = new IPAddressString(addrString);
+
+ // If this isn't a valid address, subnet, etc., throw an exception
+ if (!ipString.isIPAddress())
+ throw new GuacamoleServerException("Invalid IP address specified: " + addrString);
+
+ // Add the address to the list.
+ ipAddresses.add(ipString.getAddress());
+ }
+
+ // Return our list of valid IP addresses and/or subnets
+ return ipAddresses;
+
+ }
+
+ /**
+ * Return true if the provided address list contains the client address,
+ * or false if no match is found.
+ *
+ * @param addrList
+ * The address list to check for matches.
+ *
+ * @param ipAddr
+ * The client address to look for in the list.
+ *
+ * @return
+ * True if the client address is in the provided list, otherwise
+ * false.
+ */
+ public static boolean addressListContains(List addrList, IPAddress ipAddr) {
+
+ // If either is null, return false
+ if (ipAddr == null || addrList == null)
+ return false;
+
+ for (IPAddress ipEntry : addrList)
+
+ // If version matches and entry contains it, return true
+ if (ipEntry.getIPVersion().equals(ipAddr.getIPVersion())
+ && ipEntry.contains(ipAddr))
+ return true;
+
+ // No match, so return false
+ return false;
+
+ }
+
+}
diff --git a/guacamole-ext/src/main/java/org/apache/guacamole/properties/IntegerGuacamoleProperty.java b/guacamole-ext/src/main/java/org/apache/guacamole/properties/IntegerGuacamoleProperty.java
index 2228e2ea2..8746f2774 100644
--- a/guacamole-ext/src/main/java/org/apache/guacamole/properties/IntegerGuacamoleProperty.java
+++ b/guacamole-ext/src/main/java/org/apache/guacamole/properties/IntegerGuacamoleProperty.java
@@ -19,6 +19,9 @@
package org.apache.guacamole.properties;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
import org.apache.guacamole.GuacamoleException;
import org.apache.guacamole.GuacamoleServerException;
@@ -42,5 +45,26 @@ public abstract class IntegerGuacamoleProperty implements GuacamoleProperty parseValueCollection(String value) throws GuacamoleException {
+
+ if (value == null)
+ return null;
+
+ // Split string into a list of individual values
+ List stringValues = Arrays.asList(DELIMITER_PATTERN.split(value));
+ if (stringValues.isEmpty())
+ return null;
+
+ // Translate values to Integers, validating along the way.
+ List intValues = new ArrayList<>();
+ for (String stringInt : stringValues) {
+ intValues.add(parseValue(stringInt));
+ }
+
+ return intValues;
+
+ }
}
diff --git a/guacamole-ext/src/main/java/org/apache/guacamole/properties/LongGuacamoleProperty.java b/guacamole-ext/src/main/java/org/apache/guacamole/properties/LongGuacamoleProperty.java
index 9c25d6f50..b118a6140 100644
--- a/guacamole-ext/src/main/java/org/apache/guacamole/properties/LongGuacamoleProperty.java
+++ b/guacamole-ext/src/main/java/org/apache/guacamole/properties/LongGuacamoleProperty.java
@@ -19,6 +19,9 @@
package org.apache.guacamole.properties;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
import org.apache.guacamole.GuacamoleException;
import org.apache.guacamole.GuacamoleServerException;
@@ -42,5 +45,26 @@ public abstract class LongGuacamoleProperty implements GuacamoleProperty {
}
}
+
+ @Override
+ public List parseValueCollection(String value) throws GuacamoleException {
+
+ if (value == null)
+ return null;
+
+ // Split string into a list of individual values
+ List stringValues = Arrays.asList(DELIMITER_PATTERN.split(value));
+ if (stringValues.isEmpty())
+ return null;
+
+ // Translate values to Longs, validating along the way.
+ List longValues = new ArrayList<>();
+ for (String stringLong : stringValues) {
+ longValues.add(parseValue(stringLong));
+ }
+
+ return longValues;
+
+ }
}
diff --git a/guacamole-ext/src/main/java/org/apache/guacamole/properties/StringGuacamoleProperty.java b/guacamole-ext/src/main/java/org/apache/guacamole/properties/StringGuacamoleProperty.java
index 0d3756ab1..abc2b15cb 100644
--- a/guacamole-ext/src/main/java/org/apache/guacamole/properties/StringGuacamoleProperty.java
+++ b/guacamole-ext/src/main/java/org/apache/guacamole/properties/StringGuacamoleProperty.java
@@ -19,6 +19,8 @@
package org.apache.guacamole.properties;
+import java.util.Arrays;
+import java.util.List;
import org.apache.guacamole.GuacamoleException;
/**
@@ -30,5 +32,20 @@ public abstract class StringGuacamoleProperty implements GuacamoleProperty parseValueCollection(String value) throws GuacamoleException {
+
+ if (value == null)
+ return null;
+
+ // Split string into a list of individual values
+ List stringValues = Arrays.asList(DELIMITER_PATTERN.split(value));
+ if (stringValues.isEmpty())
+ return null;
+
+ return stringValues;
+
+ }
}
diff --git a/guacamole-ext/src/main/java/org/apache/guacamole/properties/StringListProperty.java b/guacamole-ext/src/main/java/org/apache/guacamole/properties/StringListProperty.java
index 0bb81423c..574a3d8ca 100644
--- a/guacamole-ext/src/main/java/org/apache/guacamole/properties/StringListProperty.java
+++ b/guacamole-ext/src/main/java/org/apache/guacamole/properties/StringListProperty.java
@@ -31,17 +31,14 @@ import org.apache.guacamole.GuacamoleException;
* compatibility with the behavior of Java properties in general, only
* whitespace at the beginning of each value is ignored; trailing whitespace
* becomes part of the value.
+ *
+ * @deprecated
+ * This class is now deprecated in favor of using the StringGuacamoleProperty
+ * class with the parseValueCollection method.
*/
+@Deprecated
public abstract class StringListProperty implements GuacamoleProperty> {
- /**
- * A pattern which matches against the delimiters between values. This is
- * currently simply a comma and any following whitespace. Parts of the
- * input string which match this pattern will not be included in the parsed
- * result.
- */
- private static final Pattern DELIMITER_PATTERN = Pattern.compile(",\\s*");
-
@Override
public List parseValue(String values) throws GuacamoleException {
diff --git a/guacamole-ext/src/main/java/org/apache/guacamole/properties/TimeZoneGuacamoleProperty.java b/guacamole-ext/src/main/java/org/apache/guacamole/properties/TimeZoneGuacamoleProperty.java
index a294bda67..d4a15f977 100644
--- a/guacamole-ext/src/main/java/org/apache/guacamole/properties/TimeZoneGuacamoleProperty.java
+++ b/guacamole-ext/src/main/java/org/apache/guacamole/properties/TimeZoneGuacamoleProperty.java
@@ -19,6 +19,9 @@
package org.apache.guacamole.properties;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
import java.util.TimeZone;
import java.util.regex.Pattern;
import org.apache.guacamole.GuacamoleException;
@@ -57,4 +60,25 @@ public abstract class TimeZoneGuacamoleProperty
}
+ @Override
+ public List parseValueCollection(String value) throws GuacamoleException {
+
+ if (value == null)
+ return null;
+
+ // Split string into a list of individual values
+ List stringValues = Arrays.asList(DELIMITER_PATTERN.split(value));
+ if (stringValues.isEmpty())
+ return null;
+
+ // Translate values to Integers, validating along the way.
+ List tzValues = new ArrayList<>();
+ for (String stringTz : stringValues) {
+ tzValues.add(parseValue(stringTz));
+ }
+
+ return tzValues;
+
+ }
+
}
diff --git a/guacamole-ext/src/main/java/org/apache/guacamole/properties/URIGuacamoleProperty.java b/guacamole-ext/src/main/java/org/apache/guacamole/properties/URIGuacamoleProperty.java
index 7f53bf834..ae6077c7b 100644
--- a/guacamole-ext/src/main/java/org/apache/guacamole/properties/URIGuacamoleProperty.java
+++ b/guacamole-ext/src/main/java/org/apache/guacamole/properties/URIGuacamoleProperty.java
@@ -21,6 +21,9 @@ package org.apache.guacamole.properties;
import java.net.URI;
import java.net.URISyntaxException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
import org.apache.guacamole.GuacamoleException;
import org.apache.guacamole.GuacamoleServerException;
@@ -46,4 +49,26 @@ public abstract class URIGuacamoleProperty implements GuacamoleProperty {
}
+ @Override
+ public List parseValueCollection(String value) throws GuacamoleException {
+
+ // Nothing provided, return nothing.
+ if (value == null)
+ return null;
+
+ // Split string into a list of individual values
+ List stringValues = Arrays.asList(DELIMITER_PATTERN.split(value));
+ if (stringValues.isEmpty())
+ return null;
+
+ // Translate values to URIs, validating along the way.
+ List uriValues = new ArrayList<>();
+ for (String stringUri : stringValues) {
+ uriValues.add(parseValue(stringUri));
+ }
+
+ return uriValues;
+
+ }
+
}
diff --git a/guacamole/pom.xml b/guacamole/pom.xml
index 6cae5dc10..b0743b0fd 100644
--- a/guacamole/pom.xml
+++ b/guacamole/pom.xml
@@ -26,14 +26,14 @@
org.apache.guacamole
guacamole
war
- 1.5.5
+ 1.6.0
guacamole
http://guacamole.apache.org/
org.apache.guacamole
guacamole-client
- 1.5.5
+ 1.6.0
../
@@ -254,14 +254,14 @@
org.apache.guacamole
guacamole-ext
- 1.5.5
+ 1.6.0
org.apache.guacamole
guacamole-common-js
- 1.5.5
+ 1.6.0
zip
runtime
diff --git a/guacamole/src/main/frontend/src/app/manage/directives/systemPermissionEditor.js b/guacamole/src/main/frontend/src/app/manage/directives/systemPermissionEditor.js
index 78377a7d5..079c0d03f 100644
--- a/guacamole/src/main/frontend/src/app/manage/directives/systemPermissionEditor.js
+++ b/guacamole/src/main/frontend/src/app/manage/directives/systemPermissionEditor.js
@@ -121,6 +121,10 @@ angular.module('manage').directive('systemPermissionEditor', ['$injector',
label: "MANAGE_USER.FIELD_HEADER_ADMINISTER_SYSTEM",
value: PermissionSet.SystemPermissionType.ADMINISTER
},
+ {
+ label: "MANAGE_USER.FIELD_HEADER_AUDIT_SYSTEM",
+ value: PermissionSet.SystemPermissionType.AUDIT
+ },
{
label: "MANAGE_USER.FIELD_HEADER_CREATE_NEW_USERS",
value: PermissionSet.SystemPermissionType.CREATE_USER
diff --git a/guacamole/src/main/frontend/src/app/navigation/services/userPageService.js b/guacamole/src/main/frontend/src/app/navigation/services/userPageService.js
index aeb701a33..9a9f693f6 100644
--- a/guacamole/src/main/frontend/src/app/navigation/services/userPageService.js
+++ b/guacamole/src/main/frontend/src/app/navigation/services/userPageService.js
@@ -298,8 +298,9 @@ angular.module('navigation').factory('userPageService', ['$injector',
// Determine whether the current user needs access to view connection history
if (
- // A user must be a system administrator to view connection records
- PermissionSet.hasSystemPermission(permissions, PermissionSet.SystemPermissionType.ADMINISTER)
+ // A user must be a system administrator or auditor to view connection records
+ PermissionSet.hasSystemPermission(permissions, PermissionSet.SystemPermissionType.ADMINISTER)
+ || PermissionSet.hasSystemPermission(permissions, PermissionSet.SystemPermissionType.AUDIT)
) {
canViewConnectionRecords.push(dataSource);
}
@@ -312,7 +313,7 @@ angular.module('navigation').factory('userPageService', ['$injector',
url : '/settings/sessions'
}));
- // If user can manage connections, add links for connection management pages
+ // If user can view connection records, add links for connection history pages
angular.forEach(canViewConnectionRecords, function addConnectionHistoryLink(dataSource) {
pages.push(new PageDefinition({
name : [
diff --git a/guacamole/src/main/frontend/src/app/rest/types/PermissionSet.js b/guacamole/src/main/frontend/src/app/rest/types/PermissionSet.js
index 9dd1ac8d6..2a549456b 100644
--- a/guacamole/src/main/frontend/src/app/rest/types/PermissionSet.js
+++ b/guacamole/src/main/frontend/src/app/rest/types/PermissionSet.js
@@ -136,6 +136,11 @@ angular.module('rest').factory('PermissionSet', [function definePermissionSet()
* Permission to administer the entire system.
*/
ADMINISTER : "ADMINISTER",
+
+ /**
+ * Permission to view connection and user records for the entire system.
+ */
+ AUDIT : "AUDIT",
/**
* Permission to create new users.
diff --git a/guacamole/src/main/frontend/src/translations/en.json b/guacamole/src/main/frontend/src/translations/en.json
index 1c7e08a82..d02968787 100644
--- a/guacamole/src/main/frontend/src/translations/en.json
+++ b/guacamole/src/main/frontend/src/translations/en.json
@@ -408,6 +408,7 @@
"ERROR_PASSWORD_MISMATCH" : "@:APP.ERROR_PASSWORD_MISMATCH",
"FIELD_HEADER_ADMINISTER_SYSTEM" : "Administer system:",
+ "FIELD_HEADER_AUDIT_SYSTEM" : "Audit system:",
"FIELD_HEADER_CHANGE_OWN_PASSWORD" : "Change own password:",
"FIELD_HEADER_CREATE_NEW_USERS" : "Create new users:",
"FIELD_HEADER_CREATE_NEW_USER_GROUPS" : "Create new user groups:",
@@ -449,6 +450,7 @@
"DIALOG_HEADER_ERROR" : "@:APP.DIALOG_HEADER_ERROR",
"FIELD_HEADER_ADMINISTER_SYSTEM" : "@:MANAGE_USER.FIELD_HEADER_ADMINISTER_SYSTEM",
+ "FIELD_HEADER_AUDIT_SYSTEM" : "@:MANAGE_USER.FIELD_HEADER_AUDIT_SYSTEM",
"FIELD_HEADER_CHANGE_OWN_PASSWORD" : "@:MANAGE_USER.FIELD_HEADER_CHANGE_OWN_PASSWORD",
"FIELD_HEADER_CREATE_NEW_USERS" : "@:MANAGE_USER.FIELD_HEADER_CREATE_NEW_USERS",
"FIELD_HEADER_CREATE_NEW_USER_GROUPS" : "@:MANAGE_USER.FIELD_HEADER_CREATE_NEW_USER_GROUPS",
diff --git a/guacamole/src/main/java/org/apache/guacamole/extension/ExtensionModule.java b/guacamole/src/main/java/org/apache/guacamole/extension/ExtensionModule.java
index b0f6537a7..c4744e2d9 100644
--- a/guacamole/src/main/java/org/apache/guacamole/extension/ExtensionModule.java
+++ b/guacamole/src/main/java/org/apache/guacamole/extension/ExtensionModule.java
@@ -74,7 +74,8 @@ public class ExtensionModule extends ServletModule {
"1.5.2",
"1.5.3",
"1.5.4",
- "1.5.5"
+ "1.5.5",
+ "1.6.0"
));
/**
diff --git a/pom.xml b/pom.xml
index c3c242d80..a2155f4e3 100644
--- a/pom.xml
+++ b/pom.xml
@@ -26,7 +26,7 @@
org.apache.guacamole
guacamole-client
pom
- 1.5.5
+ 1.6.0
guacamole-client
http://guacamole.apache.org/