GUACAMOLE-189: Allow per-connection guacd parameters for the JDBC auth.

Project: http://git-wip-us.apache.org/repos/asf/incubator-guacamole-client/repo
Commit: 
http://git-wip-us.apache.org/repos/asf/incubator-guacamole-client/commit/152de87d
Tree: 
http://git-wip-us.apache.org/repos/asf/incubator-guacamole-client/tree/152de87d
Diff: 
http://git-wip-us.apache.org/repos/asf/incubator-guacamole-client/diff/152de87d

Branch: refs/heads/master
Commit: 152de87dc21260c3a9f25c1a0e9eee78900a3cda
Parents: 1c0ee41
Author: Michael Jumper <[email protected]>
Authored: Sat Oct 22 20:19:18 2016 -0700
Committer: Michael Jumper <[email protected]>
Committed: Thu May 4 21:32:23 2017 -0700

----------------------------------------------------------------------
 .../guacamole/auth/jdbc/JDBCEnvironment.java    |  38 +++++
 .../auth/jdbc/connection/ConnectionModel.java   |  92 ++++++++++++
 .../connection/GuacamoleProxyConfiguration.java | 132 +++++++++++++++++
 .../auth/jdbc/connection/ModeledConnection.java | 140 ++++++++++++++++++-
 .../tunnel/AbstractGuacamoleTunnelService.java  |  77 +++++-----
 .../src/main/resources/translations/en.json     |  11 +-
 .../schema/upgrade/upgrade-pre-0.9.13.sql       |  30 ++++
 .../auth/jdbc/connection/ConnectionMapper.xml   |  34 ++++-
 .../schema/upgrade/upgrade-pre-0.9.13.sql       |  35 +++++
 .../auth/jdbc/connection/ConnectionMapper.xml   |  34 ++++-
 10 files changed, 572 insertions(+), 51 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-guacamole-client/blob/152de87d/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/JDBCEnvironment.java
----------------------------------------------------------------------
diff --git 
a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/JDBCEnvironment.java
 
b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/JDBCEnvironment.java
index dfbf0e9..52aed03 100644
--- 
a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/JDBCEnvironment.java
+++ 
b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/JDBCEnvironment.java
@@ -20,6 +20,8 @@
 package org.apache.guacamole.auth.jdbc;
 
 import org.apache.guacamole.GuacamoleException;
+import org.apache.guacamole.auth.jdbc.connection.GuacamoleProxyConfiguration;
+import org.apache.guacamole.environment.Environment;
 import org.apache.guacamole.environment.LocalEnvironment;
 import org.apache.guacamole.auth.jdbc.security.PasswordPolicy;
 
@@ -30,6 +32,18 @@ import 
org.apache.guacamole.auth.jdbc.security.PasswordPolicy;
 public abstract class JDBCEnvironment extends LocalEnvironment {
     
     /**
+     * The hostname to use when connecting to guacd if no hostname is provided
+     * within guacamole.properties.
+     */
+    private static final String DEFAULT_GUACD_HOSTNAME = "localhost";
+
+    /**
+     * The port to use when connecting to guacd if no port is provided within
+     * guacamole.properties.
+     */
+    private static final int DEFAULT_GUACD_PORT = 4822;
+
+    /**
      * Constructs a new JDBCEnvironment using an underlying LocalEnviroment to
      * read properties from the file system.
      * 
@@ -41,6 +55,30 @@ public abstract class JDBCEnvironment extends 
LocalEnvironment {
     }
 
     /**
+     * Returns the connection information which should be used, by default, to
+     * connect to guacd when establishing a remote desktop connection.
+     *
+     * @return
+     *     The connection information which should be used, by default, to
+     *     connect to guacd.
+     *
+     * @throws GuacamoleException
+     *     If the properties describing the connection information for guacd
+     *     cannot be parsed.
+     */
+    public GuacamoleProxyConfiguration getDefaultGuacamoleProxyConfiguration()
+            throws GuacamoleException {
+
+        // Parse guacd hostname/port/ssl properties
+        return new GuacamoleProxyConfiguration(
+            getProperty(Environment.GUACD_HOSTNAME, DEFAULT_GUACD_HOSTNAME),
+            getProperty(Environment.GUACD_PORT, DEFAULT_GUACD_PORT),
+            getProperty(Environment.GUACD_SSL, false)
+        );
+
+    }
+
+    /**
      * Returns whether a database user account is required for authentication 
to
      * succeed, even if another authentication provider has already
      * authenticated the user.

http://git-wip-us.apache.org/repos/asf/incubator-guacamole-client/blob/152de87d/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/connection/ConnectionModel.java
----------------------------------------------------------------------
diff --git 
a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/connection/ConnectionModel.java
 
b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/connection/ConnectionModel.java
index ac10455..92346b7 100644
--- 
a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/connection/ConnectionModel.java
+++ 
b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/connection/ConnectionModel.java
@@ -22,6 +22,7 @@ package org.apache.guacamole.auth.jdbc.connection;
 import java.util.HashSet;
 import java.util.Set;
 import org.apache.guacamole.auth.jdbc.base.ChildObjectModel;
+import 
org.apache.guacamole.auth.jdbc.connection.GuacamoleProxyConfiguration.EncryptionMethod;
 
 /**
  * Object representation of a Guacamole connection, as represented in the
@@ -60,6 +61,24 @@ public class ConnectionModel extends ChildObjectModel {
     private Set<String> sharingProfileIdentifiers = new HashSet<String>();
 
     /**
+     * The hostname of the guacd instance to use, or null if the hostname of 
the
+     * default guacd instance should be used.
+     */
+    private String proxyHostname;
+
+    /**
+     * The port of the guacd instance to use, or null if the port of the 
default
+     * guacd instance should be used.
+     */
+    private Integer proxyPort;
+
+    /**
+     * The encryption method required by the desired guacd instance, or null if
+     * the encryption method of the default guacd instance should be used.
+     */
+    private EncryptionMethod proxyEncryptionMethod;
+
+    /**
      * Creates a new, empty connection.
      */
     public ConnectionModel() {
@@ -159,6 +178,79 @@ public class ConnectionModel extends ChildObjectModel {
     }
 
     /**
+     * Returns the hostname of the guacd instance to use. If the hostname of 
the
+     * default guacd instance should be used instead, null is returned.
+     *
+     * @return
+     *     The hostname of the guacd instance to use, or null if the hostname
+     *     of the default guacd instance should be used.
+     */
+    public String getProxyHostname() {
+        return proxyHostname;
+    }
+
+    /**
+     * Sets the hostname of the guacd instance to use.
+     *
+     * @param proxyHostname
+     *     The hostname of the guacd instance to use, or null if the hostname
+     *     of the default guacd instance should be used.
+     */
+    public void setProxyHostname(String proxyHostname) {
+        this.proxyHostname = proxyHostname;
+    }
+
+    /**
+     * Returns the port of the guacd instance to use. If the port of the 
default
+     * guacd instance should be used instead, null is returned.
+     *
+     * @return
+     *     The port of the guacd instance to use, or null if the port of the
+     *     default guacd instance should be used.
+     */
+    public Integer getProxyPort() {
+        return proxyPort;
+    }
+
+    /**
+     * Sets the port of the guacd instance to use.
+     *
+     * @param proxyPort
+     *     The port of the guacd instance to use, or null if the port of the
+     *     default guacd instance should be used.
+     */
+    public void setProxyPort(Integer proxyPort) {
+        this.proxyPort = proxyPort;
+    }
+
+    /**
+     * Returns the type of encryption required by the desired guacd instance.
+     * If the encryption method of the default guacd instance should be used
+     * instead, null is returned.
+     *
+     * @return
+     *     The type of encryption required by the desired guacd instance, or
+     *     null if the encryption method of the default guacd instance should
+     *     be used.
+     */
+    public EncryptionMethod getProxyEncryptionMethod() {
+        return proxyEncryptionMethod;
+    }
+
+    /**
+     * Sets the type of encryption which should be used when connecting to
+     * guacd, if any.
+     *
+     * @param proxyEncryptionMethod
+     *     The type of encryption required by the desired guacd instance, or
+     *     null if the encryption method of the default guacd instance should
+     *     be used.
+     */
+    public void setProxyEncryptionMethod(EncryptionMethod 
proxyEncryptionMethod) {
+        this.proxyEncryptionMethod = proxyEncryptionMethod;
+    }
+
+    /**
      * Returns the identifiers of all readable sharing profiles associated with
      * this connection. This is set only when the connection is queried, and 
has
      * no effect when a connection is inserted, updated, or deleted.

http://git-wip-us.apache.org/repos/asf/incubator-guacamole-client/blob/152de87d/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/connection/GuacamoleProxyConfiguration.java
----------------------------------------------------------------------
diff --git 
a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/connection/GuacamoleProxyConfiguration.java
 
b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/connection/GuacamoleProxyConfiguration.java
new file mode 100644
index 0000000..28d02e8
--- /dev/null
+++ 
b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/connection/GuacamoleProxyConfiguration.java
@@ -0,0 +1,132 @@
+/*
+ * 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.jdbc.connection;
+
+/**
+ * Information which describes how the connection to guacd should be
+ * established. This includes the hostname and port which guacd is listening 
on,
+ * as well as the type of encryption required, if any.
+ *
+ * @author Michael Jumper
+ */
+public class GuacamoleProxyConfiguration {
+
+    /**
+     * All possible types of encryption used by guacd.
+     */
+    public enum EncryptionMethod {
+
+        /**
+         * Unencrypted (plaintext).
+         */
+        NONE,
+
+        /**
+         * Encrypted with SSL or TLS.
+         */
+        SSL
+        
+    }
+
+    /**
+     * The hostname or address of the machine where guacd is running.
+     */
+    private final String hostname;
+
+    /**
+     * The port that guacd is listening on.
+     */
+    private final int port;
+
+    /**
+     * The type of encryption required by guacd.
+     */
+    private final EncryptionMethod encryptionMethod;
+
+    /**
+     * Creates a new GuacamoleProxyConfiguration having the given hostname,
+     * port, and encryption method.
+     *
+     * @param hostname
+     *     The hostname or address of the machine where guacd is running.
+     *
+     * @param port
+     *     The port that guacd is listening on.
+     *
+     * @param encryptionMethod
+     *     The type of encryption required by the instance of guacd running at
+     *     the given hostname and port.
+     */
+    public GuacamoleProxyConfiguration(String hostname, int port,
+            EncryptionMethod encryptionMethod) {
+        this.hostname = hostname;
+        this.port = port;
+        this.encryptionMethod = encryptionMethod;
+    }
+
+    /**
+     * Creates a new GuacamoleProxyConfiguration having the given hostname and
+     * port, with encryption method being restricted to either NONE or SSL.
+     *
+     * @param hostname
+     *     The hostname or address of the machine where guacd is running.
+     *
+     * @param port
+     *     The port that guacd is listening on.
+     *
+     * @param ssl
+     *     true if guacd requires SSL/TLS encryption, false if communication
+     *     with guacd should be unencrypted.
+     */
+    public GuacamoleProxyConfiguration(String hostname, int port, boolean ssl) 
{
+        this(hostname, port, ssl ? EncryptionMethod.SSL : 
EncryptionMethod.NONE);
+    }
+
+    /**
+     * Returns the hostname or address of the machine where guacd is running.
+     *
+     * @return
+     *     The hostname or address of the machine where guacd is running.
+     */
+    public String getHostname() {
+        return hostname;
+    }
+
+    /**
+     * Returns the port that guacd is listening on.
+     *
+     * @return
+     *     The port that guacd is listening on.
+     */
+    public int getPort() {
+        return port;
+    }
+
+    /**
+     * Returns the type of encryption required by guacd.
+     *
+     * @return
+     *     The type of encryption required by guacd.
+     */
+    public EncryptionMethod getEncryptionMethod() {
+        return encryptionMethod;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-guacamole-client/blob/152de87d/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/connection/ModeledConnection.java
----------------------------------------------------------------------
diff --git 
a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/connection/ModeledConnection.java
 
b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/connection/ModeledConnection.java
index cbfdb68..2de235c 100644
--- 
a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/connection/ModeledConnection.java
+++ 
b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/connection/ModeledConnection.java
@@ -32,9 +32,12 @@ import 
org.apache.guacamole.auth.jdbc.tunnel.GuacamoleTunnelService;
 import org.apache.guacamole.GuacamoleException;
 import org.apache.guacamole.auth.jdbc.JDBCEnvironment;
 import org.apache.guacamole.auth.jdbc.base.ModeledChildDirectoryObject;
+import 
org.apache.guacamole.auth.jdbc.connection.GuacamoleProxyConfiguration.EncryptionMethod;
+import org.apache.guacamole.form.EnumField;
 import org.apache.guacamole.form.Field;
 import org.apache.guacamole.form.Form;
 import org.apache.guacamole.form.NumericField;
+import org.apache.guacamole.form.TextField;
 import org.apache.guacamole.net.GuacamoleTunnel;
 import org.apache.guacamole.net.auth.Connection;
 import org.apache.guacamole.net.auth.ConnectionRecord;
@@ -56,6 +59,51 @@ public class ModeledConnection extends 
ModeledChildDirectoryObject<ConnectionMod
     private static final Logger logger = 
LoggerFactory.getLogger(ModeledConnection.class);
 
     /**
+     * The name of the attribute which overrides the hostname used to connect
+     * to guacd for this connection.
+     */
+    public static final String GUACD_HOSTNAME_NAME = "guacd-hostname";
+
+    /**
+     * The name of the attribute which overrides the port used to connect to
+     * guacd for this connection.
+     */
+    public static final String GUACD_PORT_NAME = "guacd-port";
+
+    /**
+     * The name of the attribute which overrides the encryption method used to
+     * connect to guacd for this connection.
+     */
+    public static final String GUACD_ENCRYPTION_NAME = "guacd-encryption";
+
+    /**
+     * The value specified for the "guacd-encryption" attribute if encryption
+     * should not be used to connect to guacd.
+     */
+    public static final String GUACD_ENCRYPTION_VALUE_NONE = "none";
+
+    /**
+     * The value specified for the "guacd-encryption" attribute if SSL/TLS
+     * encryption should be used to connect to guacd.
+     */
+    public static final String GUACD_ENCRYPTION_VALUE_SSL = "ssl";
+
+    /**
+     * All attributes which describe the configuration of the guacd instance
+     * which will be used to connect to the remote desktop described by this
+     * connection.
+     */
+    public static final Form GUACD_PARAMETERS = new Form("guacd", 
Arrays.<Field>asList(
+        new TextField(GUACD_HOSTNAME_NAME),
+        new NumericField(GUACD_PORT_NAME),
+        new EnumField(GUACD_ENCRYPTION_NAME, Arrays.asList(
+            "",
+            GUACD_ENCRYPTION_VALUE_NONE,
+            GUACD_ENCRYPTION_VALUE_SSL
+        ))
+    ));
+
+    /**
      * The name of the attribute which controls the maximum number of
      * concurrent connections.
      */
@@ -81,7 +129,8 @@ public class ModeledConnection extends 
ModeledChildDirectoryObject<ConnectionMod
      * logical forms.
      */
     public static final Collection<Form> ATTRIBUTES = 
Collections.unmodifiableCollection(Arrays.asList(
-        CONCURRENCY_LIMITS
+        CONCURRENCY_LIMITS,
+        GUACD_PARAMETERS
     ));
 
     /**
@@ -186,6 +235,35 @@ public class ModeledConnection extends 
ModeledChildDirectoryObject<ConnectionMod
         // Set per-user connection limit attribute
         attributes.put(MAX_CONNECTIONS_PER_USER_NAME, 
NumericField.format(getModel().getMaxConnectionsPerUser()));
 
+        // Set guacd (proxy) hostname and port
+        attributes.put(GUACD_HOSTNAME_NAME, getModel().getProxyHostname());
+        attributes.put(GUACD_PORT_NAME, 
NumericField.format(getModel().getProxyPort()));
+
+        // Set guacd (proxy) encryption method
+        EncryptionMethod encryptionMethod = 
getModel().getProxyEncryptionMethod();
+        if (encryptionMethod == null)
+            attributes.put(GUACD_ENCRYPTION_NAME, null);
+
+        else {
+            switch (encryptionMethod) {
+
+                // Unencrypted
+                case NONE:
+                    attributes.put(GUACD_ENCRYPTION_NAME, 
GUACD_ENCRYPTION_VALUE_NONE);
+                    break;
+
+                // SSL / TLS encryption
+                case SSL:
+                    attributes.put(GUACD_ENCRYPTION_NAME, 
GUACD_ENCRYPTION_VALUE_SSL);
+                    break;
+
+                // Unimplemented / unspecified
+                default:
+                    attributes.put(GUACD_ENCRYPTION_NAME, null);
+
+            }
+        }
+
         return attributes;
     }
 
@@ -206,6 +284,31 @@ public class ModeledConnection extends 
ModeledChildDirectoryObject<ConnectionMod
             logger.debug("Unable to parse numeric attribute.", e);
         }
 
+        // Set guacd hostname (no translation necessary)
+        getModel().setProxyHostname(attributes.get(GUACD_HOSTNAME_NAME));
+
+        // Translate guacd port
+        try { 
getModel().setProxyPort(NumericField.parse(attributes.get(GUACD_PORT_NAME))); }
+        catch (NumberFormatException e) {
+            logger.warn("Not setting guacd port: {}", e.getMessage());
+            logger.debug("Unable to parse numeric attribute.", e);
+        }
+
+        // Translate guacd encryption method
+        String encryptionMethod = attributes.get(GUACD_ENCRYPTION_NAME);
+
+        // Unencrypted
+        if (GUACD_ENCRYPTION_VALUE_NONE.equals(encryptionMethod))
+            getModel().setProxyEncryptionMethod(EncryptionMethod.NONE);
+
+        // SSL / TLS
+        else if (GUACD_ENCRYPTION_VALUE_SSL.equals(encryptionMethod))
+            getModel().setProxyEncryptionMethod(EncryptionMethod.SSL);
+
+        // Unimplemented / unspecified
+        else
+            getModel().setProxyEncryptionMethod(null);
+
     }
 
     /**
@@ -257,4 +360,39 @@ public class ModeledConnection extends 
ModeledChildDirectoryObject<ConnectionMod
 
     }
 
+    /**
+     * Returns the connection information which should be used to connect to
+     * guacd when establishing a connection to the remote desktop described by
+     * this connection. If no such information is defined for this specific
+     * remote desktop connection, the default guacd connection information will
+     * be used instead, as defined by JDBCEnvironment.
+     *
+     * @return
+     *     The connection information which should be used to connect to guacd
+     *     when establishing a connection to the remote desktop described by
+     *     this connection.
+     *
+     * @throws GuacamoleException
+     *     If the connection information for guacd cannot be parsed.
+     */
+    public GuacamoleProxyConfiguration getGuacamoleProxyConfiguration()
+            throws GuacamoleException {
+
+        // Retrieve default proxy configuration from environment
+        GuacamoleProxyConfiguration defaultConfig = 
environment.getDefaultGuacamoleProxyConfiguration();
+
+        // Retrieve proxy configuration overrides from model
+        String hostname = getModel().getProxyHostname();
+        Integer port = getModel().getProxyPort();
+        EncryptionMethod encryptionMethod = 
getModel().getProxyEncryptionMethod();
+
+        // Produce new proxy configuration from model, using defaults where 
unspecified
+        return new GuacamoleProxyConfiguration(
+            hostname         != null ? hostname         : 
defaultConfig.getHostname(),
+            port             != null ? port             : 
defaultConfig.getPort(),
+            encryptionMethod != null ? encryptionMethod : 
defaultConfig.getEncryptionMethod()
+        );
+
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/incubator-guacamole-client/blob/152de87d/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/tunnel/AbstractGuacamoleTunnelService.java
----------------------------------------------------------------------
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 043029c..abdeaff 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
@@ -42,10 +42,10 @@ import org.apache.guacamole.GuacamoleException;
 import org.apache.guacamole.GuacamoleResourceConflictException;
 import org.apache.guacamole.GuacamoleResourceNotFoundException;
 import org.apache.guacamole.GuacamoleSecurityException;
+import org.apache.guacamole.GuacamoleServerException;
 import org.apache.guacamole.GuacamoleUpstreamException;
 import org.apache.guacamole.auth.jdbc.JDBCEnvironment;
 import org.apache.guacamole.auth.jdbc.connection.ConnectionMapper;
-import org.apache.guacamole.environment.Environment;
 import org.apache.guacamole.net.GuacamoleSocket;
 import org.apache.guacamole.net.GuacamoleTunnel;
 import org.apache.guacamole.net.auth.Connection;
@@ -57,6 +57,7 @@ import org.apache.guacamole.token.StandardTokens;
 import org.apache.guacamole.token.TokenFilter;
 import org.mybatis.guice.transactional.Transactional;
 import org.apache.guacamole.auth.jdbc.connection.ConnectionParameterMapper;
+import org.apache.guacamole.auth.jdbc.connection.GuacamoleProxyConfiguration;
 import 
org.apache.guacamole.auth.jdbc.sharing.connection.SharedConnectionDefinition;
 import org.apache.guacamole.auth.jdbc.sharingprofile.ModeledSharingProfile;
 import 
org.apache.guacamole.auth.jdbc.sharingprofile.SharingProfileParameterMapper;
@@ -80,12 +81,6 @@ public abstract class AbstractGuacamoleTunnelService 
implements GuacamoleTunnelS
     private final Logger logger = 
LoggerFactory.getLogger(AbstractGuacamoleTunnelService.class);
 
     /**
-     * The environment of the Guacamole server.
-     */
-    @Inject
-    private JDBCEnvironment environment;
- 
-    /**
      * Mapper for accessing connections.
      */
     @Inject
@@ -122,18 +117,6 @@ public abstract class AbstractGuacamoleTunnelService 
implements GuacamoleTunnelS
     private Provider<ActiveConnectionRecord> activeConnectionRecordProvider;
 
     /**
-     * The hostname to use when connecting to guacd if no hostname is provided
-     * within guacamole.properties.
-     */
-    private static final String DEFAULT_GUACD_HOSTNAME = "localhost";
-
-    /**
-     * The port to use when connecting to guacd if no port is provided within
-     * guacamole.properties.
-     */
-    private static final int DEFAULT_GUACD_PORT = 4822;
-
-    /**
      * All active connections through the tunnel having a given UUID.
      */
     private final Map<String, ActiveConnectionRecord> activeTunnels =
@@ -333,6 +316,13 @@ public abstract class AbstractGuacamoleTunnelService 
implements GuacamoleTunnelS
      * Returns an unconfigured GuacamoleSocket that is already connected to
      * guacd as specified in guacamole.properties, using SSL if necessary.
      *
+     * @param proxyConfig
+     *     The configuration information to use when connecting to guacd.
+     *
+     * @param socketClosedCallback
+     *     The callback which should be invoked whenever the returned socket
+     *     closes.
+     *
      * @return
      *     An unconfigured GuacamoleSocket, already connected to guacd.
      *
@@ -340,23 +330,33 @@ public abstract class AbstractGuacamoleTunnelService 
implements GuacamoleTunnelS
      *     If an error occurs while connecting to guacd, or while parsing
      *     guacd-related properties.
      */
-    private GuacamoleSocket getUnconfiguredGuacamoleSocket(Runnable 
socketClosedCallback)
-        throws GuacamoleException {
+    private GuacamoleSocket getUnconfiguredGuacamoleSocket(
+            GuacamoleProxyConfiguration proxyConfig,
+            Runnable socketClosedCallback) throws GuacamoleException {
+
+        // Select socket type depending on desired encryption
+        switch (proxyConfig.getEncryptionMethod()) {
+
+            // Use SSL if requested
+            case SSL:
+                return new ManagedSSLGuacamoleSocket(
+                    proxyConfig.getHostname(),
+                    proxyConfig.getPort(),
+                    socketClosedCallback
+                );
+
+            // Use straight TCP if unencrypted
+            case NONE:
+                return new ManagedInetGuacamoleSocket(
+                    proxyConfig.getHostname(),
+                    proxyConfig.getPort(),
+                    socketClosedCallback
+                );
 
-        // Use SSL if requested
-        if (environment.getProperty(Environment.GUACD_SSL, false))
-            return new ManagedSSLGuacamoleSocket(
-                environment.getProperty(Environment.GUACD_HOSTNAME, 
DEFAULT_GUACD_HOSTNAME),
-                environment.getProperty(Environment.GUACD_PORT,     
DEFAULT_GUACD_PORT),
-                socketClosedCallback
-            );
-
-        // Otherwise, just use straight TCP
-        return new ManagedInetGuacamoleSocket(
-            environment.getProperty(Environment.GUACD_HOSTNAME, 
DEFAULT_GUACD_HOSTNAME),
-            environment.getProperty(Environment.GUACD_PORT,     
DEFAULT_GUACD_PORT),
-            socketClosedCallback
-        );
+        }
+
+        // Bail out if encryption method is unknown
+        throw new GuacamoleServerException("Unimplemented encryption method.");
 
     }
 
@@ -472,10 +472,12 @@ public abstract class AbstractGuacamoleTunnelService 
implements GuacamoleTunnelS
 
             GuacamoleConfiguration config;
 
+            // Retrieve connection information associated with given 
connection record
+            ModeledConnection connection = activeConnection.getConnection();
+
             // Pull configuration directly from the connection if we are not
             // joining an active connection
             if (activeConnection.isPrimaryConnection()) {
-                ModeledConnection connection = 
activeConnection.getConnection();
                 activeConnections.put(connection.getIdentifier(), 
activeConnection);
                 activeConnectionGroups.put(connection.getParentIdentifier(), 
activeConnection);
                 config = getGuacamoleConfiguration(activeConnection.getUser(), 
connection);
@@ -499,7 +501,8 @@ public abstract class AbstractGuacamoleTunnelService 
implements GuacamoleTunnelS
 
             // Obtain socket which will automatically run the cleanup task
             ConfiguredGuacamoleSocket socket = new ConfiguredGuacamoleSocket(
-                getUnconfiguredGuacamoleSocket(cleanupTask), config, info);
+                
getUnconfiguredGuacamoleSocket(connection.getGuacamoleProxyConfiguration(),
+                        cleanupTask), config, info);
 
             // Assign and return new tunnel
             if (interceptErrors)

http://git-wip-us.apache.org/repos/asf/incubator-guacamole-client/blob/152de87d/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/resources/translations/en.json
----------------------------------------------------------------------
diff --git 
a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/resources/translations/en.json
 
b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/resources/translations/en.json
index 78728c3..f182aac 100644
--- 
a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/resources/translations/en.json
+++ 
b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/resources/translations/en.json
@@ -20,7 +20,16 @@
         "FIELD_HEADER_MAX_CONNECTIONS"          : "Maximum number of 
connections:",
         "FIELD_HEADER_MAX_CONNECTIONS_PER_USER" : "Maximum number of 
connections per user:",
 
-        "SECTION_HEADER_CONCURRENCY" : "Concurrency Limits"
+        "FIELD_HEADER_GUACD_HOSTNAME"   : "Hostname:",
+        "FIELD_HEADER_GUACD_ENCRYPTION" : "Encryption:",
+        "FIELD_HEADER_GUACD_PORT"       : "Port:",
+
+        "FIELD_OPTION_GUACD_ENCRYPTION_EMPTY" : "",
+        "FIELD_OPTION_GUACD_ENCRYPTION_NONE"  : "None (unencrypted)",
+        "FIELD_OPTION_GUACD_ENCRYPTION_SSL"   : "SSL / TLS",
+
+        "SECTION_HEADER_CONCURRENCY" : "Concurrency Limits",
+        "SECTION_HEADER_GUACD"       : "Guacamole Proxy Parameters (guacd)"
 
     },
 

http://git-wip-us.apache.org/repos/asf/incubator-guacamole-client/blob/152de87d/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/schema/upgrade/upgrade-pre-0.9.13.sql
----------------------------------------------------------------------
diff --git 
a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/schema/upgrade/upgrade-pre-0.9.13.sql
 
b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/schema/upgrade/upgrade-pre-0.9.13.sql
new file mode 100644
index 0000000..bb37c6c
--- /dev/null
+++ 
b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/schema/upgrade/upgrade-pre-0.9.13.sql
@@ -0,0 +1,30 @@
+--
+-- 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 guacd per-connection override columns
+--
+
+ALTER TABLE guacamole_connection ADD COLUMN proxy_port INT(11);
+ALTER TABLE guacamole_connection ADD COLUMN proxy_hostname VARCHAR(512);
+
+ALTER TABLE guacamole_connection ADD COLUMN proxy_encryption_method ENUM(
+    'NONE',
+    'SSL'
+);

http://git-wip-us.apache.org/repos/asf/incubator-guacamole-client/blob/152de87d/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/src/main/resources/org/apache/guacamole/auth/jdbc/connection/ConnectionMapper.xml
----------------------------------------------------------------------
diff --git 
a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/src/main/resources/org/apache/guacamole/auth/jdbc/connection/ConnectionMapper.xml
 
b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/src/main/resources/org/apache/guacamole/auth/jdbc/connection/ConnectionMapper.xml
index 0fd0265..e4b5294 100644
--- 
a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/src/main/resources/org/apache/guacamole/auth/jdbc/connection/ConnectionMapper.xml
+++ 
b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/src/main/resources/org/apache/guacamole/auth/jdbc/connection/ConnectionMapper.xml
@@ -33,6 +33,10 @@
         <result column="protocol"                 property="protocol"          
    jdbcType="VARCHAR"/>
         <result column="max_connections"          property="maxConnections"    
    jdbcType="INTEGER"/>
         <result column="max_connections_per_user" 
property="maxConnectionsPerUser" jdbcType="INTEGER"/>
+        <result column="proxy_hostname"           property="proxyHostname"     
    jdbcType="VARCHAR"/>
+        <result column="proxy_port"               property="proxyPort"         
    jdbcType="INTEGER"/>
+        <result column="proxy_encryption_method"  
property="proxyEncryptionMethod" jdbcType="VARCHAR"
+                
javaType="org.apache.guacamole.auth.jdbc.connection.GuacamoleProxyConfiguration$EncryptionMethod"/>
 
         <!-- Associated sharing profiles -->
         <collection property="sharingProfileIdentifiers" 
resultSet="sharingProfiles" ofType="java.lang.String"
@@ -88,7 +92,10 @@
             parent_id,
             protocol,
             max_connections,
-            max_connections_per_user
+            max_connections_per_user,
+            proxy_hostname,
+            proxy_port,
+            proxy_encryption_method
         FROM guacamole_connection
         WHERE connection_id IN
             <foreach collection="identifiers" item="identifier"
@@ -116,7 +123,10 @@
             parent_id,
             protocol,
             max_connections,
-            max_connections_per_user
+            max_connections_per_user,
+            proxy_hostname,
+            proxy_port,
+            proxy_encryption_method
         FROM guacamole_connection
         JOIN guacamole_connection_permission ON 
guacamole_connection_permission.connection_id = 
guacamole_connection.connection_id
         WHERE guacamole_connection.connection_id IN
@@ -149,7 +159,10 @@
             parent_id,
             protocol,
             max_connections,
-            max_connections_per_user
+            max_connections_per_user,
+            proxy_hostname,
+            proxy_port,
+            proxy_encryption_method
         FROM guacamole_connection
         WHERE 
             <if test="parentIdentifier != null">parent_id = 
#{parentIdentifier,jdbcType=VARCHAR}</if>
@@ -173,14 +186,20 @@
             parent_id,
             protocol,
             max_connections,
-            max_connections_per_user
+            max_connections_per_user,
+            proxy_hostname,
+            proxy_port,
+            proxy_encryption_method
         )
         VALUES (
             #{object.name,jdbcType=VARCHAR},
             #{object.parentIdentifier,jdbcType=VARCHAR},
             #{object.protocol,jdbcType=VARCHAR},
             #{object.maxConnections,jdbcType=INTEGER},
-            #{object.maxConnectionsPerUser,jdbcType=INTEGER}
+            #{object.maxConnectionsPerUser,jdbcType=INTEGER},
+            #{object.proxyHostname,jdbcType=VARCHAR},
+            #{object.proxyPort,jdbcType=INTEGER},
+            #{object.proxyEncryptionMethod,jdbcType=VARCHAR}
         )
 
     </insert>
@@ -192,7 +211,10 @@
             parent_id                = 
#{object.parentIdentifier,jdbcType=VARCHAR},
             protocol                 = #{object.protocol,jdbcType=VARCHAR},
             max_connections          = 
#{object.maxConnections,jdbcType=INTEGER},
-            max_connections_per_user = 
#{object.maxConnectionsPerUser,jdbcType=INTEGER}
+            max_connections_per_user = 
#{object.maxConnectionsPerUser,jdbcType=INTEGER},
+            proxy_hostname           = 
#{object.proxyHostname,jdbcType=VARCHAR},
+            proxy_port               = #{object.proxyPort,jdbcType=INTEGER},
+            proxy_encryption_method  = 
#{object.proxyEncryptionMethod,jdbcType=VARCHAR}
         WHERE connection_id = #{object.objectID,jdbcType=INTEGER}
     </update>
 

http://git-wip-us.apache.org/repos/asf/incubator-guacamole-client/blob/152de87d/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/schema/upgrade/upgrade-pre-0.9.13.sql
----------------------------------------------------------------------
diff --git 
a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/schema/upgrade/upgrade-pre-0.9.13.sql
 
b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/schema/upgrade/upgrade-pre-0.9.13.sql
new file mode 100644
index 0000000..015ec9a
--- /dev/null
+++ 
b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/schema/upgrade/upgrade-pre-0.9.13.sql
@@ -0,0 +1,35 @@
+--
+-- 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 guacd encryption method type
+--
+
+CREATE TYPE guacamole_proxy_encryption_method AS ENUM(
+    'NONE',
+    'SSL'
+);
+
+--
+-- Add guacd per-connection override columns
+--
+
+ALTER TABLE guacamole_connection ADD COLUMN proxy_port integer;
+ALTER TABLE guacamole_connection ADD COLUMN proxy_hostname varchar(512);
+ALTER TABLE guacamole_connection ADD COLUMN proxy_encryption_method 
guacamole_proxy_encryption_method;

http://git-wip-us.apache.org/repos/asf/incubator-guacamole-client/blob/152de87d/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/src/main/resources/org/apache/guacamole/auth/jdbc/connection/ConnectionMapper.xml
----------------------------------------------------------------------
diff --git 
a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/src/main/resources/org/apache/guacamole/auth/jdbc/connection/ConnectionMapper.xml
 
b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/src/main/resources/org/apache/guacamole/auth/jdbc/connection/ConnectionMapper.xml
index 5fe9de4..aedd86b 100644
--- 
a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/src/main/resources/org/apache/guacamole/auth/jdbc/connection/ConnectionMapper.xml
+++ 
b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/src/main/resources/org/apache/guacamole/auth/jdbc/connection/ConnectionMapper.xml
@@ -33,6 +33,10 @@
         <result column="protocol"                 property="protocol"          
    jdbcType="VARCHAR"/>
         <result column="max_connections"          property="maxConnections"    
    jdbcType="INTEGER"/>
         <result column="max_connections_per_user" 
property="maxConnectionsPerUser" jdbcType="INTEGER"/>
+        <result column="proxy_hostname"           property="proxyHostname"     
    jdbcType="VARCHAR"/>
+        <result column="proxy_port"               property="proxyPort"         
    jdbcType="INTEGER"/>
+        <result column="proxy_encryption_method"  
property="proxyEncryptionMethod" jdbcType="VARCHAR"
+                
javaType="org.apache.guacamole.auth.jdbc.connection.GuacamoleProxyConfiguration$EncryptionMethod"/>
 
         <!-- Associated sharing profiles -->
         <collection property="sharingProfileIdentifiers" 
resultSet="sharingProfiles" ofType="java.lang.String"
@@ -88,7 +92,10 @@
             parent_id,
             protocol,
             max_connections,
-            max_connections_per_user
+            max_connections_per_user,
+            proxy_hostname,
+            proxy_port,
+            proxy_encryption_method
         FROM guacamole_connection
         WHERE connection_id IN
             <foreach collection="identifiers" item="identifier"
@@ -116,7 +123,10 @@
             parent_id,
             protocol,
             max_connections,
-            max_connections_per_user
+            max_connections_per_user,
+            proxy_hostname,
+            proxy_port,
+            proxy_encryption_method
         FROM guacamole_connection
         JOIN guacamole_connection_permission ON 
guacamole_connection_permission.connection_id = 
guacamole_connection.connection_id
         WHERE guacamole_connection.connection_id IN
@@ -149,7 +159,10 @@
             parent_id,
             protocol,
             max_connections,
-            max_connections_per_user
+            max_connections_per_user,
+            proxy_hostname,
+            proxy_port,
+            proxy_encryption_method
         FROM guacamole_connection
         WHERE 
             <if test="parentIdentifier != null">parent_id = 
#{parentIdentifier,jdbcType=INTEGER}::integer</if>
@@ -173,14 +186,20 @@
             parent_id,
             protocol,
             max_connections,
-            max_connections_per_user
+            max_connections_per_user,
+            proxy_hostname,
+            proxy_port,
+            proxy_encryption_method
         )
         VALUES (
             #{object.name,jdbcType=VARCHAR},
             #{object.parentIdentifier,jdbcType=INTEGER}::integer,
             #{object.protocol,jdbcType=VARCHAR},
             #{object.maxConnections,jdbcType=INTEGER},
-            #{object.maxConnectionsPerUser,jdbcType=INTEGER}
+            #{object.maxConnectionsPerUser,jdbcType=INTEGER},
+            #{object.proxyHostname,jdbcType=VARCHAR},
+            #{object.proxyPort,jdbcType=INTEGER},
+            
#{object.proxyEncryptionMethod,jdbcType=VARCHAR}::guacamole_proxy_encryption_method
         )
 
     </insert>
@@ -192,7 +211,10 @@
             parent_id                = 
#{object.parentIdentifier,jdbcType=INTEGER}::integer,
             protocol                 = #{object.protocol,jdbcType=VARCHAR},
             max_connections          = 
#{object.maxConnections,jdbcType=INTEGER},
-            max_connections_per_user = 
#{object.maxConnectionsPerUser,jdbcType=INTEGER}
+            max_connections_per_user = 
#{object.maxConnectionsPerUser,jdbcType=INTEGER},
+            proxy_hostname           = 
#{object.proxyHostname,jdbcType=VARCHAR},
+            proxy_port               = #{object.proxyPort,jdbcType=INTEGER},
+            proxy_encryption_method  = 
#{object.proxyEncryptionMethod,jdbcType=VARCHAR}::guacamole_proxy_encryption_method
         WHERE connection_id = #{object.objectID,jdbcType=INTEGER}::integer
     </update>
 


Reply via email to