keycloak-uncached

KEYCLOAK-2903 Fix WelcomeResource to not allow requests forwarded

4/26/2016 5:33:33 AM

Details

diff --git a/common/src/main/java/org/keycloak/common/ClientConnection.java b/common/src/main/java/org/keycloak/common/ClientConnection.java
index 3c4b449..5afbed6 100755
--- a/common/src/main/java/org/keycloak/common/ClientConnection.java
+++ b/common/src/main/java/org/keycloak/common/ClientConnection.java
@@ -24,7 +24,11 @@ package org.keycloak.common;
  * @version $Revision: 1 $
  */
 public interface ClientConnection {
+
     String getRemoteAddr();
     String getRemoteHost();
-    int getReportPort();
+    int getRemotePort();
+
+    String getLocalAddr();
+    int getLocalPort();
 }
diff --git a/services/src/main/java/org/keycloak/services/filters/KeycloakSessionServletFilter.java b/services/src/main/java/org/keycloak/services/filters/KeycloakSessionServletFilter.java
index d6a3f13..282fd31 100755
--- a/services/src/main/java/org/keycloak/services/filters/KeycloakSessionServletFilter.java
+++ b/services/src/main/java/org/keycloak/services/filters/KeycloakSessionServletFilter.java
@@ -63,9 +63,19 @@ public class KeycloakSessionServletFilter implements Filter {
             }
 
             @Override
-            public int getReportPort() {
+            public int getRemotePort() {
                 return request.getRemotePort();
             }
+
+            @Override
+            public String getLocalAddr() {
+                return request.getLocalAddr();
+            }
+
+            @Override
+            public int getLocalPort() {
+                return request.getLocalPort();
+            }
         };
         session.getContext().setConnection(connection);
         ResteasyProviderFactory.pushContext(ClientConnection.class, connection);
diff --git a/services/src/main/java/org/keycloak/services/resources/WelcomeResource.java b/services/src/main/java/org/keycloak/services/resources/WelcomeResource.java
index 54becb9..d57f0fe 100755
--- a/services/src/main/java/org/keycloak/services/resources/WelcomeResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/WelcomeResource.java
@@ -20,14 +20,11 @@ import org.keycloak.Config;
 import org.keycloak.common.ClientConnection;
 import org.keycloak.common.util.MimeTypeUtil;
 import org.keycloak.models.BrowserSecurityHeaders;
-import org.keycloak.models.Constants;
 import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.RealmModel;
 import org.keycloak.models.utils.KeycloakModelUtils;
 import org.keycloak.services.ForbiddenException;
 import org.keycloak.services.ServicesLogger;
 import org.keycloak.services.managers.ApplianceBootstrap;
-import org.keycloak.services.managers.AuthenticationManager;
 import org.keycloak.services.util.CacheControlUtil;
 import org.keycloak.services.util.CookieHelper;
 import org.keycloak.theme.BrowserSecurityHeaderSetup;
@@ -225,13 +222,24 @@ public class WelcomeResource {
 
     private boolean isLocal() {
         try {
-            InetAddress inetAddress = InetAddress.getByName(session.getContext().getConnection().getRemoteAddr());
-            return inetAddress.isAnyLocalAddress() || inetAddress.isLoopbackAddress();
+            ClientConnection clientConnection = session.getContext().getConnection();
+            InetAddress remoteInetAddress = InetAddress.getByName(clientConnection.getRemoteAddr());
+            InetAddress localInetAddress = InetAddress.getByName(clientConnection.getLocalAddr());
+            String xForwardedFor = headers.getHeaderString("X-Forwarded-For");
+            logger.debugf("Checking WelcomePage. Remote address: %s, Local address: %s, X-Forwarded-For header: %s", remoteInetAddress.toString(), localInetAddress.toString(), xForwardedFor);
+
+            // Access through AJP protocol (loadbalancer) may cause that remoteAddress is "127.0.0.1".
+            // So consider that welcome page accessed locally just if it was accessed really through "localhost" URL and without loadbalancer (x-forwarded-for header is empty).
+            return isLocalAddress(remoteInetAddress) && isLocalAddress(localInetAddress) && xForwardedFor == null;
         } catch (UnknownHostException e) {
             throw new WebApplicationException(Response.Status.INTERNAL_SERVER_ERROR);
         }
     }
 
+    private boolean isLocalAddress(InetAddress inetAddress) {
+        return inetAddress.isAnyLocalAddress() || inetAddress.isLoopbackAddress();
+    }
+
     private String updateCsrfChecks() {
         String stateChecker = getCsrfCookie();
         if (stateChecker != null) {