On 2019-03-21 00:12, brian mullan wrote:
> Maybe I missed it but what linux distro are you using ?
Brian, I think it does not matter so much. I have compiled guacd from sources 
for Debian Buster and I have downloaded guacamole.war v1.0.0 from Apache 
website.

On 2019-03-21 15:33, Nick Couchman wrote:
> I don't think that the not allowing of a null password is actually the issue 
> - I think the problem is that it just implements the 
> getAuthorizedConfigurations() method and not the authenticateUser()
> method, which is what the other modules use to "stack" authentication.
Nick, if you check SimpleAuthenticationProvider.authenticateUser():142
<https://github.com/apache/guacamole-client/blob/7e7b6fde4cd63ac8ec21e2ee900ae865d15a4c36/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/simple/SimpleAuthenticationProvider.java#L142>
 you
will see that if there are configurations available, user is created on-the-fly.
Further look into the source code revealed that things are a bit more 
complicated. All modules perform user comparison based on the information from 
Credentials instance, see for example
UserService.retrieveAuthenticatedUser():361
<https://github.com/apache/guacamole-client/blob/658ce7884695cbe0c04b29f0b6fa365312dbe2fd/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/user/UserService.java#L361>
and the only place where this object is created at is 
TokenRESTService.getCredentials()
<https://github.com/apache/guacamole-client/blob/c890919d5bbb9ccc8243f04caae07c78a032ef07/guacamole/src/main/java/org/apache/guacamole/rest/auth/TokenRESTService.java#L84>.
 That in its turn means that
Guacamole cannot create Credentials instance other than from Authorization: 
Basic HTTP header, which means that front webserver/proxy authorization (which 
is not necessarily HTTP basic authentication)
is not possible.

I have identified the following workarounds, namely, if one of below patches is 
applied then everything starts working:

  * FileAuthenticationProvider.java.patch – this one overrides getUserContext() 
to enable configuration for authenticatedUser.getIdentifier().
  * AuthenticatedUser_Authorization.patch – this one injects username from 
header to Credentials and allows null passwords.


>  
>
>     How Guacamole decides in which order to call providers? I order is 
> undefined, then I don't see any reasonable way to make chaining possible. The 
> only way out then is for
>     HTTPHeaderAuthenticationProvider to extend FileAuthenticationProvider...
>
>
> In general extensions are loaded and processed in alphabetical order, but 
> FileAuthenticationProvider is always loaded and processed last.  However, the 
> overall order only matters in certain corner
> cases for stacking, and, in this case, the order does not matter so much as 
> the fact that FileAuthenticationProvider does not implement 
> authenticateUser().  I could be wrong about that, but I'm
> reasonably certain that's the issue.
Thanks. I confirm that is exactly as you say.

>  
>
>     As for HTTPHeaderAuthenticationProvider implementation, I am a bit 
> concerned. It uses such powerful tool as Guice / IoC just to perform static 
> bindings? Then it's an overkill.
>
>
> HTTPHeaderAuthenticationProvider only uses Guice to process configuration 
> information.  It is quite possible it is slightly overkill for this 
> implementation, and you're certainly welcome to propose
> changes and submit pull requests if you have an idea of how it can be done 
> more efficiently.
>  
>
>>     You say that you don't get automatically connected to the VNC server - 
>> do you see the connection at all on the home screen?  Or is it a blank 
>> screen, with no connections?
>     I don't see any connections on home screen. In other words, I see only 
> blank white panes.
>
>
> Yeah, this further indicates that the File provider does not stack with the 
> other modules.
>  
>
>>     My suggestion would be to use the JDBC module to store connections.  It 
>> requires a little bit of extra work and a few extra resources to configure, 
>> but definitey works with the other modules
>>     and also gives you some flexibility in permission management among users.
>     I would like not to go that way. Maybe it's not so complicated to setup, 
> but I would like to keep everything simple.
>
>
> That's understandable; however, this means you really have two options:
> - Write a custom module, similar to the FileAuthenticationProvider, that 
> reads input from a file and stacks correctly with other modules.  This should 
> be pretty straight-forward, especially if you
> just want to write a module that contains configurations and not actual 
> authentication information, and just map users or groups to those 
> configurations.
With my respect to GUACAMOLE-493 
<https://issues.apache.org/jira/browse/GUACAMOLE-493> and GUACAMOLE-256 
<https://issues.apache.org/jira/browse/GUACAMOLE-256> after removing 
guacamole-auth-noauth
Guacamole provided no means to replace it. It actually did what you say, and 
only was missing a header check.

> - Propose changes to the FileAuthenticationProvider that allows it to "stack" 
> with the other modules, and (possibly, if you're up to it) submit a pull 
> request for those changes and have that
> functionality added to a future version (1.1.0 scope is fixed, so it would be 
> 1.2.0 or later).
As I shown above, "stacking" of FileAuthenticationProvider is possible, but 
requires opening other doors, which I am not sure is correct.

>  
>
>>      The File provider handles both cases - either the single connection 
>> specified within the <authorize></authorize> context, or multiple 
>> connections specified within their own
>>     <connection></connection> contexts.
>     Could you please put that phrase into documentation? As an option I can 
> create a pull request.
>
>
> http://guacamole.apache.org/doc/gug/configuring-guacamole.html#basic-auth
>  
> We can be more explicit about it if you think it necessary, but I'm 
> reasonably certain the examples in the documentation cover both scenarios.
>
Thanks for comments & explanations!

-- 
With best regards,
Dmitry

--- 
guacamole/src/main/java/org/apache/guacamole/auth/file/FileAuthenticationProvider.java.orig
 2018-12-05 23:32:37.000000000 +0100
+++ 
guacamole/src/main/java/org/apache/guacamole/auth/file/FileAuthenticationProvider.java
      2019-03-22 00:48:56.393284100 +0100
@@ -28,8 +28,11 @@
 import org.apache.guacamole.GuacamoleException;
 import org.apache.guacamole.environment.Environment;
 import org.apache.guacamole.environment.LocalEnvironment;
+import org.apache.guacamole.net.auth.AuthenticatedUser;
 import org.apache.guacamole.net.auth.Credentials;
+import org.apache.guacamole.net.auth.UserContext;
 import org.apache.guacamole.net.auth.simple.SimpleAuthenticationProvider;
+import org.apache.guacamole.net.auth.simple.SimpleUserContext;
 import org.apache.guacamole.xml.DocumentHandler;
 import org.apache.guacamole.protocol.GuacamoleConfiguration;
 import org.slf4j.Logger;
@@ -169,6 +172,34 @@
 
     }
 
+    @Override
+    public UserContext getUserContext(AuthenticatedUser authenticatedUser)
+            throws GuacamoleException {
+
+        Map<String, GuacamoleConfiguration> configs =
+                
getAuthorizedConfigurations(authenticatedUser.getCredentials());
+
+        if (configs == null) {
+            // Abort authorization if no user mapping exists
+            UserMapping userMapping = getUserMapping();
+            if (userMapping == null)
+                return null;
+
+            // Validate and return info for given user and pass
+            Authorization auth = 
userMapping.getAuthorization(authenticatedUser.getIdentifier());
+
+            if (auth != null)
+               configs = auth.getConfigurations();
+
+            if (configs == null)
+               return null;
+        }
+
+        // Return user context restricted to authorized configs
+        return new SimpleUserContext(this, authenticatedUser.getIdentifier(), 
configs);
+
+    }
+
     @Override
     public Map<String, GuacamoleConfiguration>
             getAuthorizedConfigurations(Credentials credentials)
--- 
extensions/guacamole-auth-header/src/main/java/org/apache/guacamole/auth/header/user/AuthenticatedUser.java.orig
    2018-12-05 23:32:37.000000000 +0100
+++ 
extensions/guacamole-auth-header/src/main/java/org/apache/guacamole/auth/header/user/AuthenticatedUser.java
 2019-03-22 00:54:57.597802800 +0100
@@ -54,8 +54,9 @@
      *     The credentials provided when this user was authenticated.
      */
     public void init(String username, Credentials credentials) {
-        this.credentials = credentials;
         setIdentifier(username.toLowerCase());
+        this.credentials = credentials;
+        this.credentials.setUsername(getIdentifier());
     }
 
     @Override
--- 
guacamole/src/main/java/org/apache/guacamole/auth/file/Authorization.java.orig  
    2018-12-05 23:32:37.000000000 +0100
+++ guacamole/src/main/java/org/apache/guacamole/auth/file/Authorization.java   
2019-03-22 01:16:34.969670500 +0100
@@ -23,6 +23,7 @@
 import java.security.MessageDigest;
 import java.security.NoSuchAlgorithmException;
 import java.util.Map;
+import java.util.Objects;
 import java.util.TreeMap;
 import org.apache.guacamole.protocol.GuacamoleConfiguration;
 
@@ -178,8 +179,7 @@
     public boolean validate(String username, String password) {
 
         // If username matches
-        if (username != null && password != null
-                && username.equals(this.username)) {
+        if (username != null && username.equals(this.username)) {
 
             switch (encoding) {
 
@@ -187,7 +187,7 @@
                 case PLAIN_TEXT:
 
                     // Compare plaintext
-                    return password.equals(this.password);
+                    return Objects.equals(password, this.password);
 
                 // If hased with MD5, hash password and compare
                 case MD5:

Reply via email to