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]