diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/glyptodon/guacamole/auth/jdbc/user/AuthenticatedUser.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/glyptodon/guacamole/auth/jdbc/user/AuthenticatedUser.java index f778bbb44..480000e62 100644 --- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/glyptodon/guacamole/auth/jdbc/user/AuthenticatedUser.java +++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/glyptodon/guacamole/auth/jdbc/user/AuthenticatedUser.java @@ -22,6 +22,8 @@ package org.glyptodon.guacamole.auth.jdbc.user; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import javax.servlet.http.HttpServletRequest; import org.glyptodon.guacamole.net.auth.Credentials; @@ -47,9 +49,34 @@ public class AuthenticatedUser { */ private final String remoteHost; + /** + * Regular expression which matches any IPv4 address. + */ + private static final String IPV4_ADDRESS_REGEX = "([0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3})"; + + /** + * Regular expression which matches any IPv6 address. + */ + private static final String IPV6_ADDRESS_REGEX = "([0-9a-fA-F]*(:[0-9a-fA-F]*){0,7})"; + + /** + * Regular expression which matches any IP address, regardless of version. + */ + private static final String IP_ADDRESS_REGEX = "(" + IPV4_ADDRESS_REGEX + "|" + IPV6_ADDRESS_REGEX + ")"; + + /** + * Pattern which matches valid values of the de-facto standard + * "X-Forwarded-For" header. + */ + private static final Pattern X_FORWARDED_FOR = Pattern.compile("^" + IP_ADDRESS_REGEX + "(, " + IP_ADDRESS_REGEX + ")*$"); + /** * Derives the remote host of the authenticating user from the given - * credentials object. + * credentials object. The remote host is derived from X-Forwarded-For + * in addition to the actual source IP of the request, and thus is not + * trusted. The derived remote host is really only useful for logging, + * unless the server is configured such that X-Forwarded-For is guaranteed + * to be trustworthy. * * @param credentials * The credentials to derive the remote host from. @@ -59,8 +86,20 @@ public class AuthenticatedUser { * authenticating. */ private static String getRemoteHost(Credentials credentials) { + HttpServletRequest request = credentials.getRequest(); + + // Use X-Forwarded-For, if present and valid + String header = request.getHeader("X-Forwarded-For"); + if (header != null) { + Matcher matcher = X_FORWARDED_FOR.matcher(header); + if (matcher.matches()) + return matcher.group(1); + } + + // If header absent or invalid, just use source IP return request.getRemoteAddr(); + } /**