This is an automated email from the ASF dual-hosted git repository.

vavrtom pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/qpid-broker-j.git


The following commit(s) were added to refs/heads/main by this push:
     new cd281e0e5d QPID-8593: [Broker-J] Header validation in management-http 
plugin (#134)
cd281e0e5d is described below

commit cd281e0e5d1cd68a6514fc972f7a8b5c5bdc385c
Author: Daniil Kirilyuk <[email protected]>
AuthorDate: Tue Jul 26 11:59:15 2022 +0200

    QPID-8593: [Broker-J] Header validation in management-http plugin (#134)
    
    * QPID-8593: [Broker-J] Header validation in management-http plugin
    
    * QPID-8593: [Broker-J] Added new line to end of file
    
    Co-authored-by: vavrtom <[email protected]>
---
 .../server/management/plugin/HttpManagement.java   |  9 +++++
 .../plugin/HttpManagementConfiguration.java        |  6 ++++
 .../plugin/servlet/rest/AbstractServlet.java       | 39 ++++++++++++++++++++--
 .../plugin/servlet/rest/RestServlet.java           |  9 +++--
 4 files changed, 57 insertions(+), 6 deletions(-)

diff --git 
a/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/HttpManagement.java
 
b/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/HttpManagement.java
index 7581605848..71221fa6dd 100644
--- 
a/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/HttpManagement.java
+++ 
b/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/HttpManagement.java
@@ -177,6 +177,9 @@ public class HttpManagement extends 
AbstractPluginAdapter<HttpManagement> implem
     @ManagedAttributeField
     public String _corsAllowHeaders;
 
+    @ManagedAttributeField
+    public Set<String> _allowedResponseHeaders;
+
     @ManagedAttributeField
     public boolean _corsAllowCredentials;
 
@@ -291,6 +294,12 @@ public class HttpManagement extends 
AbstractPluginAdapter<HttpManagement> implem
         return _corsAllowHeaders;
     }
 
+    @Override
+    public Set<String> getAllowedResponseHeaders()
+    {
+        return _allowedResponseHeaders;
+    }
+
     @Override
     public boolean getCorsAllowCredentials()
     {
diff --git 
a/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/HttpManagementConfiguration.java
 
b/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/HttpManagementConfiguration.java
index 571441971d..aaaecee831 100644
--- 
a/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/HttpManagementConfiguration.java
+++ 
b/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/HttpManagementConfiguration.java
@@ -59,6 +59,12 @@ public interface HttpManagementConfiguration<X extends 
HttpManagementConfigurati
     @ManagedAttribute( defaultValue = 
"Content-Type,Accept,Origin,X-Requested-With,X-Range" )
     String getCorsAllowHeaders();
 
+    @ManagedAttribute( defaultValue = "[\"Access-Control-Allow-Credentials\", 
\"Access-Control-Allow-Origin\", "
+        + "\"Cache-Control\", \"Content-Encoding\", \"Content-Disposition\", 
\"Content-Length\", \"Content-Type\", "
+        + "\"Date\", \"Location\", \"Expires\", \"Negotiate\", \"Pragma\", 
\"Set-Cookie\", \"Transfer-Encoding\", "
+        + "\"Vary\", \"WWW-Authenticate\"]" )
+    Set<String> getAllowedResponseHeaders();
+
     @ManagedAttribute( defaultValue = "true" )
     boolean getCorsAllowCredentials();
 
diff --git 
a/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/AbstractServlet.java
 
b/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/AbstractServlet.java
index e324c7a6f7..383fa5be39 100644
--- 
a/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/AbstractServlet.java
+++ 
b/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/AbstractServlet.java
@@ -30,7 +30,9 @@ import java.lang.reflect.Method;
 import java.nio.charset.StandardCharsets;
 import java.util.Collections;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.Map;
+import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
 import java.util.zip.GZIPOutputStream;
@@ -75,8 +77,13 @@ public abstract class AbstractServlet extends HttpServlet
     private static final Logger LOGGER = 
LoggerFactory.getLogger(AbstractServlet.class);
     public static final String CONTENT_DISPOSITION = "Content-Disposition";
 
+    /**
+     * Allowed response headers
+     */
+    private final Set<String> ALLOWED_RESPONSE_HEADERS = new HashSet<>();
+
     private transient Broker<?> _broker;
-    private transient HttpManagementConfiguration _managementConfiguration;
+    private transient HttpManagementConfiguration<?> _managementConfiguration;
     private transient final ConcurrentMap<ConfiguredObject<?>, 
ConfiguredObjectFinder> _configuredObjectFinders = new ConcurrentHashMap<>();
 
 
@@ -92,6 +99,7 @@ public abstract class AbstractServlet extends HttpServlet
         ServletContext servletContext = servletConfig.getServletContext();
         _broker = HttpManagementUtil.getBroker(servletContext);
         _managementConfiguration = 
HttpManagementUtil.getManagementConfiguration(servletContext);
+        
ALLOWED_RESPONSE_HEADERS.addAll(_managementConfiguration.getAllowedResponseHeaders());
         super.init();
     }
 
@@ -172,11 +180,12 @@ public abstract class AbstractServlet extends HttpServlet
             String filenameRfc2183 = 
ensureFilenameIsRfc2183(attachmentFilename);
             if (filenameRfc2183.length() > 0)
             {
-                response.setHeader(CONTENT_DISPOSITION, 
String.format("attachment; filename=\"%s\"", filenameRfc2183));
+                addSanitizedResponseHeader(response, CONTENT_DISPOSITION, 
String.format("attachment; filename=\"%s\"", filenameRfc2183));
             }
             else
             {
-                response.setHeader(CONTENT_DISPOSITION, "attachment");  // 
Agent will allow user to choose a name
+                // Agent will allow user to choose a name
+                addSanitizedResponseHeader(response, CONTENT_DISPOSITION, 
"attachment");
             }
         }
     }
@@ -443,5 +452,29 @@ public abstract class AbstractServlet extends HttpServlet
         return finder;
     }
 
+    /**
+     * Checks whether header may be added to response, if yes, removes 
carriage return / line feed characters from
+     * header value and adds it to the response
+     *
+     * @param response HttpServletResponse
+     * @param name Response header name
+     * @param value Response header value
+     *
+     * @return true when header was added to response, false otherwise
+     */
+    protected boolean addSanitizedResponseHeader(final HttpServletResponse 
response, final String name, String value)
+    {
+        if (ALLOWED_RESPONSE_HEADERS.contains(name))
+        {
+            if (value != null)
+            {
+                value = value.replaceAll("\\R|\\t", " ");;
+            }
+            response.setHeader(name, value);
+            return true;
+        }
+        LOGGER.info("Response header '{}' skipped, is not allowed", name);
+        return false;
+    }
 
 }
diff --git 
a/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/RestServlet.java
 
b/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/RestServlet.java
index ed41fcd764..1ad13d770b 100644
--- 
a/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/RestServlet.java
+++ 
b/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/RestServlet.java
@@ -228,13 +228,16 @@ public class RestServlet extends AbstractServlet
                               final ManagementController controller) throws 
IOException
     {
         setHeaders(response);
-        Map<String, String> headers = managementResponse.getHeaders();
+        final Map<String, String> headers = managementResponse.getHeaders();
         if (!headers.isEmpty())
         {
-            headers.forEach(response::setHeader);
+            for (final Map.Entry<String, String> entry : headers.entrySet())
+            {
+                addSanitizedResponseHeader(response, entry.getKey(), 
entry.getValue());
+            }
         }
 
-        Map<String, List<String>> parameters = 
managementRequest.getParameters();
+        final Map<String, List<String>> parameters = 
managementRequest.getParameters();
         if 
(parameters.containsKey(CONTENT_DISPOSITION_ATTACHMENT_FILENAME_PARAM))
         {
             String attachmentFilename = 
managementRequest.getParameter(CONTENT_DISPOSITION_ATTACHMENT_FILENAME_PARAM);


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to