You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@wicket.apache.org by pa...@apache.org on 2020/01/16 21:11:47 UTC
[wicket] branch csp-configurable updated: WICKET-6727: more
refactoring of the CSP API
This is an automated email from the ASF dual-hosted git repository.
papegaaij pushed a commit to branch csp-configurable
in repository https://gitbox.apache.org/repos/asf/wicket.git
The following commit(s) were added to refs/heads/csp-configurable by this push:
new a1c9bd7 WICKET-6727: more refactoring of the CSP API
a1c9bd7 is described below
commit a1c9bd7c856379c52a22a4a7b26f33da59e3bbf5
Author: Emond Papegaaij <em...@topicus.nl>
AuthorDate: Thu Jan 16 22:10:44 2020 +0100
WICKET-6727: more refactoring of the CSP API
---
.../java/org/apache/wicket/csp/CSPDirective.java | 191 +++++++++
.../wicket/csp/CSPDirectiveSandboxValue.java | 49 +++
.../apache/wicket/csp/CSPDirectiveSrcValue.java | 58 +++
.../apache/wicket/csp/CSPHeaderConfiguration.java | 143 +++++++
.../java/org/apache/wicket/csp/CSPHeaderMode.java | 45 +++
.../java/org/apache/wicket/csp/CSPRenderable.java | 42 ++
.../wicket/csp/CSPSettingRequestCycleListener.java | 441 ++-------------------
.../org/apache/wicket/csp/FixedCSPDirective.java | 50 +++
.../csp/CSPSettingRequestCycleListenerTest.java | 96 +++--
9 files changed, 665 insertions(+), 450 deletions(-)
diff --git a/wicket-core/src/main/java/org/apache/wicket/csp/CSPDirective.java b/wicket-core/src/main/java/org/apache/wicket/csp/CSPDirective.java
new file mode 100644
index 0000000..1ea52c1
--- /dev/null
+++ b/wicket-core/src/main/java/org/apache/wicket/csp/CSPDirective.java
@@ -0,0 +1,191 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.wicket.csp;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.List;
+
+import org.apache.wicket.util.string.Strings;
+
+/**
+ * An enum holding the possible CSP Directives. Via the
+ * {@link #checkValueForDirective(CSPRenderable, List)}-method, new values can be verified before
+ * being added to the list of values for a directive.
+ */
+public enum CSPDirective
+{
+ DEFAULT_SRC("default-src"),
+ SCRIPT_SRC("script-src"),
+ STYLE_SRC("style-src"),
+ IMG_SRC("img-src"),
+ CONNECT_SRC("connect-src"),
+ FONT_SRC("font-src"),
+ OBJECT_SRC("object-src"),
+ MANIFEST_SRC("manifest-src"),
+ MEDIA_SRC("media-src"),
+ CHILD_SRC("child-src"),
+ FRAME_ANCESTORS("frame-ancestors"),
+ @Deprecated
+ /** @deprecated Gebruik CHILD-SRC, deze zet ook automatisch FRAME-SRC. */
+ FRAME_SRC("frame-src"),
+ SANDBOX("sandbox")
+ {
+ @Override
+ public void checkValueForDirective(CSPRenderable value,
+ List<CSPRenderable> existingDirectiveValues)
+ {
+ if (!existingDirectiveValues.isEmpty())
+ {
+ if (CSPDirectiveSandboxValue.EMPTY.equals(value))
+ {
+ throw new IllegalArgumentException(
+ "A sandbox directive can't contain an empty string if it already contains other values ");
+ }
+ if (existingDirectiveValues.contains(CSPDirectiveSandboxValue.EMPTY))
+ {
+ throw new IllegalArgumentException(
+ "A sandbox directive can't contain other values if it already contains an empty string");
+ }
+ }
+
+ if (!(value instanceof CSPDirectiveSandboxValue))
+ {
+ throw new IllegalArgumentException(
+ "A sandbox directive can only contain values from CSPDirectiveSandboxValue or be empty");
+ }
+ }
+ },
+ REPORT_URI("report-uri")
+ {
+ @Override
+ public void checkValueForDirective(CSPRenderable value,
+ List<CSPRenderable> existingDirectiveValues)
+ {
+ if (!existingDirectiveValues.isEmpty())
+ {
+ throw new IllegalArgumentException(
+ "A report-uri directive can only contain one uri");
+ }
+ if (!(value instanceof FixedCSPDirective))
+ {
+ throw new IllegalArgumentException(
+ "A report-uri directive can only contain an URI");
+ }
+ try
+ {
+ new URI(value.render(null, null));
+ }
+ catch (URISyntaxException urise)
+ {
+ throw new IllegalArgumentException("Illegal URI for report-uri directive", urise);
+ }
+ }
+ };
+
+ private String value;
+
+ private CSPDirective(String value)
+ {
+ this.value = value;
+ }
+
+ public String getValue()
+ {
+ return value;
+ }
+
+ /**
+ * Check if {@code value} can be added to the list of other values.
+ *
+ * @param value
+ * The value to add.
+ * @param existingDirectiveValues
+ * The other values.
+ * @throws IllegalArgumentException
+ * if the given value is invalid.
+ */
+ public void checkValueForDirective(CSPRenderable value,
+ List<CSPRenderable> existingDirectiveValues)
+ {
+ if (!existingDirectiveValues.isEmpty())
+ {
+ if (CSPDirectiveSrcValue.WILDCARD.equals(value)
+ || CSPDirectiveSrcValue.NONE.equals(value))
+ {
+ throw new IllegalArgumentException(
+ "A -src directive can't contain an * or a 'none' if it already contains other values ");
+ }
+ if (existingDirectiveValues.contains(CSPDirectiveSrcValue.WILDCARD)
+ || existingDirectiveValues.contains(CSPDirectiveSrcValue.NONE))
+ {
+ throw new IllegalArgumentException(
+ "A -src directive can't contain other values if it already contains an * or a 'none'");
+ }
+ }
+
+ if (value instanceof CSPDirectiveSrcValue)
+ {
+ return;
+ }
+
+ if (value instanceof CSPDirectiveSandboxValue)
+ {
+ throw new IllegalArgumentException(
+ "A -src directive can't contain any of the sandbox directive values");
+ }
+
+ String strValue = value.render(null, null);
+ if ("data:".equals(strValue) || "https:".equals(strValue))
+ {
+ return;
+ }
+
+ // strip off "*." so "*.example.com" becomes "example.com" and we can check if
+ // it
+ // is a valid uri
+ if (strValue.startsWith("*."))
+ {
+ strValue = strValue.substring(2);
+ }
+
+ try
+ {
+ new URI(strValue);
+ }
+ catch (URISyntaxException urise)
+ {
+ throw new IllegalArgumentException("Illegal URI for -src directive", urise);
+ }
+ }
+
+ /**
+ * @return The CSPDirective constant whose value-parameter equals the input-parameter or
+ * {@code null} if none can be found.
+ */
+ public static CSPDirective fromValue(String value)
+ {
+ if (Strings.isEmpty(value))
+ return null;
+ for (int i = 0; i < values().length; i++)
+ {
+ if (value.equals(values()[i].getValue()))
+ return values()[i];
+ }
+ return null;
+ }
+}
diff --git a/wicket-core/src/main/java/org/apache/wicket/csp/CSPDirectiveSandboxValue.java b/wicket-core/src/main/java/org/apache/wicket/csp/CSPDirectiveSandboxValue.java
new file mode 100644
index 0000000..8164b31
--- /dev/null
+++ b/wicket-core/src/main/java/org/apache/wicket/csp/CSPDirectiveSandboxValue.java
@@ -0,0 +1,49 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.wicket.csp;
+
+import org.apache.wicket.request.cycle.RequestCycle;
+
+/**
+ * An enum representing the only possible values for the sandbox directive
+ */
+public enum CSPDirectiveSandboxValue implements CSPRenderable
+{
+ ALLOW_FORMS("allow-forms"),
+ ALLOW_SAME_ORIGIN("allow-same-origin"),
+ ALLOW_SCRIPTS("allow-scripts"),
+ ALLOW_TOP_NAVIGATION("allow-top-navigation"),
+ EMPTY("");
+
+ private String value;
+
+ private CSPDirectiveSandboxValue(String value)
+ {
+ this.value = value;
+ }
+
+ public String getValue()
+ {
+ return value;
+ }
+
+ @Override
+ public String render(CSPSettingRequestCycleListener listener, RequestCycle cycle)
+ {
+ return value;
+ }
+}
diff --git a/wicket-core/src/main/java/org/apache/wicket/csp/CSPDirectiveSrcValue.java b/wicket-core/src/main/java/org/apache/wicket/csp/CSPDirectiveSrcValue.java
new file mode 100644
index 0000000..b4a06db
--- /dev/null
+++ b/wicket-core/src/main/java/org/apache/wicket/csp/CSPDirectiveSrcValue.java
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.wicket.csp;
+
+import org.apache.wicket.request.cycle.RequestCycle;
+
+/**
+ * An enum holding the default values for -src directives including the mandatory single quotes
+ */
+public enum CSPDirectiveSrcValue implements CSPRenderable
+{
+ NONE("'none'"),
+ WILDCARD("*"),
+ SELF("'self'"),
+ UNSAFE_INLINE("'unsafe-inline'"),
+ UNSAFE_EVAL("'unsafe-eval'"),
+ STRICT_DYNAMIC("'strict-dynamic'"),
+ NONCE("'nonce-%1$s'")
+ {
+ @Override
+ public String render(CSPSettingRequestCycleListener listener, RequestCycle cycle)
+ {
+ return String.format(getValue(), listener.getNonce(cycle));
+ }
+ };
+
+ private String value;
+
+ private CSPDirectiveSrcValue(String value)
+ {
+ this.value = value;
+ }
+
+ @Override
+ public String render(CSPSettingRequestCycleListener listener, RequestCycle cycle)
+ {
+ return value;
+ }
+
+ public String getValue()
+ {
+ return value;
+ }
+}
diff --git a/wicket-core/src/main/java/org/apache/wicket/csp/CSPHeaderConfiguration.java b/wicket-core/src/main/java/org/apache/wicket/csp/CSPHeaderConfiguration.java
new file mode 100644
index 0000000..1abd1a5
--- /dev/null
+++ b/wicket-core/src/main/java/org/apache/wicket/csp/CSPHeaderConfiguration.java
@@ -0,0 +1,143 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.wicket.csp;
+
+import java.util.ArrayList;
+import java.util.EnumMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+import org.apache.wicket.request.cycle.RequestCycle;
+
+/**
+ *
+ * @author papegaaij
+ */
+public class CSPHeaderConfiguration
+{
+ private Map<CSPDirective, List<CSPRenderable>> directives = new EnumMap<>(CSPDirective.class);
+
+ private boolean addLegacyHeaders = false;
+
+ public CSPHeaderConfiguration()
+ {
+ }
+
+ /**
+ * True when legacy headers should be added.
+ *
+ * @return True when legacy headers should be added.
+ */
+ public boolean isAddLegacyHeaders()
+ {
+ return addLegacyHeaders;
+ }
+
+ /**
+ * Enable legacy {@code X-Content-Security-Policy} headers for older browsers, such as IE.
+ *
+ * @param addLegacyHeaders
+ * True when the legacy headers should be added.
+ * @return {@code this} for chaining
+ */
+ public CSPHeaderConfiguration setAddLegacyHeaders(boolean addLegacyHeaders)
+ {
+ this.addLegacyHeaders = addLegacyHeaders;
+ return this;
+ }
+
+ /**
+ * Adds the given values to the CSP directive on this configuraiton.
+ *
+ * @param directive
+ * The directive to add the values to.
+ * @param values
+ * The values to add.
+ */
+ public CSPHeaderConfiguration addDirective(CSPDirective directive, CSPRenderable... values)
+ {
+ for (CSPRenderable value : values)
+ {
+ doAddDirective(directive, value);
+ }
+ return this;
+ }
+
+ /**
+ * Adds a free-form value to a directive for the CSP header. This is primarily meant to used for
+ * URIs.
+ *
+ * @param directive
+ * The directive to add the values to.
+ * @param values
+ * The values to add.
+ */
+ public CSPHeaderConfiguration addDirective(CSPDirective directive, String... values)
+ {
+ for (String value : values)
+ {
+ doAddDirective(directive, new FixedCSPDirective(value));
+ }
+ return this;
+ }
+
+ /**
+ * @return true if this {@code CSPHeaderConfiguration} has any directives configured.
+ */
+ public boolean isSet()
+ {
+ return !directives.isEmpty();
+ }
+
+ @SuppressWarnings("deprecation")
+ private CSPHeaderConfiguration doAddDirective(CSPDirective directive, CSPRenderable value)
+ {
+ // Add backwards compatible frame-src
+ // see http://caniuse.com/#feat=contentsecuritypolicy2
+ if (CSPDirective.CHILD_SRC.equals(directive))
+ {
+ doAddDirective(CSPDirective.FRAME_SRC, value);
+ }
+ List<CSPRenderable> values = directives.computeIfAbsent(directive, x -> new ArrayList<>());
+ directive.checkValueForDirective(value, values);
+ values.add(value);
+ return this;
+ }
+
+ /**
+ * Renders this {@code CSPHeaderConfiguration} into an HTTP header. The returned String will be
+ * in the form {@code "key1 value1a value1b; key2 value2a; key3 value3a value3b value3c"}.
+ *
+ * @param listener
+ * The {@link CSPSettingRequestCycleListener} that renders the header.
+ * @param cycle
+ * The current {@link RequestCycle}.
+ * @return the rendered header.
+ */
+ public String renderHeaderValue(CSPSettingRequestCycleListener listener, RequestCycle cycle)
+ {
+ return directives.entrySet()
+ .stream()
+ .map(e -> e.getKey().getValue() + " "
+ + e.getValue()
+ .stream()
+ .map(r -> r.render(listener, cycle))
+ .collect(Collectors.joining(" ")))
+ .collect(Collectors.joining("; "));
+ }
+}
diff --git a/wicket-core/src/main/java/org/apache/wicket/csp/CSPHeaderMode.java b/wicket-core/src/main/java/org/apache/wicket/csp/CSPHeaderMode.java
new file mode 100644
index 0000000..48a3a95
--- /dev/null
+++ b/wicket-core/src/main/java/org/apache/wicket/csp/CSPHeaderMode.java
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.wicket.csp;
+
+/**
+ * Defines the possible headers for a CSP directive.
+ *
+ * @author papegaaij
+ */
+public enum CSPHeaderMode
+{
+ BLOCKING("Content-Security-Policy"),
+ REPORT_ONLY("Content-Security-Policy-Report-Only");
+
+ private final String header;
+
+ private CSPHeaderMode(String header)
+ {
+ this.header = header;
+ }
+
+ public String getHeader()
+ {
+ return header;
+ }
+
+ public String getLegacyHeader()
+ {
+ return "X-" + getHeader();
+ }
+}
\ No newline at end of file
diff --git a/wicket-core/src/main/java/org/apache/wicket/csp/CSPRenderable.java b/wicket-core/src/main/java/org/apache/wicket/csp/CSPRenderable.java
new file mode 100644
index 0000000..05badc9
--- /dev/null
+++ b/wicket-core/src/main/java/org/apache/wicket/csp/CSPRenderable.java
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.wicket.csp;
+
+import org.apache.wicket.request.cycle.RequestCycle;
+
+/**
+ * {@code CSPRenderable} describes a directive that is part of a Content-Security-Policy (CSP in
+ * short). Most directives are predefined in enums.
+ *
+ * @author papegaaij
+ * @see CSPDirectiveSrcValue
+ * @see CSPDirectiveSandboxValue
+ * @see FixedCSPDirective
+ */
+public interface CSPRenderable
+{
+ /**
+ * Renders the value that should be put in the CSP header.
+ *
+ * @param listener
+ * The {@link CSPSettingRequestCycleListener} that renders this value.
+ * @param cycle
+ * The current {@link RequestCycle}.
+ * @return The rendered value.
+ */
+ public String render(CSPSettingRequestCycleListener listener, RequestCycle cycle);
+}
\ No newline at end of file
diff --git a/wicket-core/src/main/java/org/apache/wicket/csp/CSPSettingRequestCycleListener.java b/wicket-core/src/main/java/org/apache/wicket/csp/CSPSettingRequestCycleListener.java
index d688990..85cff77 100644
--- a/wicket-core/src/main/java/org/apache/wicket/csp/CSPSettingRequestCycleListener.java
+++ b/wicket-core/src/main/java/org/apache/wicket/csp/CSPSettingRequestCycleListener.java
@@ -16,23 +16,19 @@
*/
package org.apache.wicket.csp;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.util.ArrayList;
-import java.util.Base64;
-import java.util.EnumMap;
import java.util.HashMap;
-import java.util.List;
import java.util.Map;
-import java.util.function.Function;
-import java.util.stream.Collectors;
+import org.apache.wicket.Application;
import org.apache.wicket.MetaDataKey;
+import org.apache.wicket.core.request.handler.BufferedResponseRequestHandler;
+import org.apache.wicket.core.request.handler.IPageClassRequestHandler;
import org.apache.wicket.request.IRequestHandler;
+import org.apache.wicket.request.IRequestHandlerDelegate;
import org.apache.wicket.request.cycle.IRequestCycleListener;
import org.apache.wicket.request.cycle.RequestCycle;
import org.apache.wicket.request.http.WebResponse;
-import org.apache.wicket.util.string.Strings;
+import org.apache.wicket.util.lang.Args;
/**
* An {@link IRequestCycleListener} that adds {@code Content-Security-Policy} and/or
@@ -78,425 +74,54 @@ public class CSPSettingRequestCycleListener implements IRequestCycleListener
private static final long serialVersionUID = 1L;
};
- public static interface CSPRenderable
- {
- public String render(CSPSettingRequestCycleListener listener, RequestCycle cycle);
- }
+ private final Application application;
+
+ private Map<CSPHeaderMode, CSPHeaderConfiguration> configs = new HashMap<>();
- private static final class FixedCSPDirective implements CSPRenderable
+ public CSPSettingRequestCycleListener(Application application)
{
- private String value;
-
- public FixedCSPDirective(String value)
- {
- if (Strings.isEmpty(value))
- throw new IllegalArgumentException(
- "CSP directive cannot have empty or null values");
- this.value = value;
- }
-
- @Override
- public String render(CSPSettingRequestCycleListener listener, RequestCycle cycle)
- {
- return value;
- }
+ this.application = Args.notNull(application, "application");
}
- /**
- * An enum holding the default values for -src directives including the mandatory single quotes
- */
- public enum CSPDirectiveSrcValue implements CSPRenderable
+ public CSPHeaderConfiguration blocking()
{
- NONE("'none'"),
- WILDCARD("*"),
- SELF("'self'"),
- UNSAFE_INLINE("'unsafe-inline'"),
- UNSAFE_EVAL("'unsafe-eval'"),
- STRICT_DYNAMIC("'strict-dynamic'"),
- NONCE("'nonce-%1$s'")
- {
- @Override
- public String render(CSPSettingRequestCycleListener listener, RequestCycle cycle)
- {
- return String.format(getValue(), listener.getNonce(cycle));
- }
- };
-
- private String value;
-
- private CSPDirectiveSrcValue(String value)
- {
- this.value = value;
- }
-
- @Override
- public String render(CSPSettingRequestCycleListener listener, RequestCycle cycle)
- {
- return value;
- }
-
- public String getValue()
- {
- return value;
- }
+ return configs.computeIfAbsent(CSPHeaderMode.BLOCKING, x -> new CSPHeaderConfiguration());
}
- /**
- * An enum representing the only possible values for the sandbox directive
- */
- public enum CSPDirectiveSandboxValue implements CSPRenderable
+ public CSPHeaderConfiguration reporting()
{
- ALLOW_FORMS("allow-forms"),
- ALLOW_SAME_ORIGIN("allow-same-origin"),
- ALLOW_SCRIPTS("allow-scripts"),
- ALLOW_TOP_NAVIGATION("allow-top-navigation"),
- EMPTY("");
-
- private String value;
-
- private CSPDirectiveSandboxValue(String value)
- {
- this.value = value;
- }
-
- public String getValue()
- {
- return value;
- }
-
- @Override
- public String render(CSPSettingRequestCycleListener listener, RequestCycle cycle)
- {
- return value;
- }
+ return configs.computeIfAbsent(CSPHeaderMode.REPORT_ONLY, x -> new CSPHeaderConfiguration());
}
- /** An enum holding the possible CSP Directives */
- public enum CSPDirective
+ protected boolean mustProtect(IRequestHandler handler)
{
- DEFAULT_SRC("default-src"),
- SCRIPT_SRC("script-src"),
- STYLE_SRC("style-src"),
- IMG_SRC("img-src"),
- CONNECT_SRC("connect-src"),
- FONT_SRC("font-src"),
- OBJECT_SRC("object-src"),
- MANIFEST_SRC("manifest-src"),
- MEDIA_SRC("media-src"),
- CHILD_SRC("child-src"),
- FRAME_ANCESTORS("frame-ancestors"),
- @Deprecated
- /** @deprecated Gebruik CHILD-SRC, deze zet ook automatisch FRAME-SRC. */
- FRAME_SRC("frame-src"),
- SANDBOX("sandbox")
- {
- @Override
- protected void checkValueForDirective(CSPRenderable value,
- List<CSPRenderable> existingDirectiveValues)
- {
- if (!existingDirectiveValues.isEmpty())
- {
- if (CSPDirectiveSandboxValue.EMPTY.equals(value))
- {
- throw new IllegalArgumentException(
- "A sandbox directive can't contain an empty string if it already contains other values ");
- }
- if (existingDirectiveValues.contains(CSPDirectiveSandboxValue.EMPTY))
- {
- throw new IllegalArgumentException(
- "A sandbox directive can't contain other values if it already contains an empty string");
- }
- }
-
- if (!(value instanceof CSPDirectiveSandboxValue))
- {
- throw new IllegalArgumentException(
- "A sandbox directive can only contain values from CSPDirectiveSandboxValue or be empty");
- }
- }
- },
- REPORT_URI("report-uri")
- {
- @Override
- protected void checkValueForDirective(CSPRenderable value,
- List<CSPRenderable> existingDirectiveValues)
- {
- if (!existingDirectiveValues.isEmpty())
- {
- throw new IllegalArgumentException(
- "A report-uri directive can only contain one uri");
- }
- if (!(value instanceof FixedCSPDirective))
- {
- throw new IllegalArgumentException(
- "A report-uri directive can only contain an URI");
- }
- try
- {
- new URI(value.render(null, null));
- }
- catch (URISyntaxException urise)
- {
- throw new IllegalArgumentException("Illegal URI for report-uri directive",
- urise);
- }
- }
- };
-
- private String value;
-
- private CSPDirective(String value)
- {
- this.value = value;
- }
-
- public String getValue()
+ if (handler instanceof IRequestHandlerDelegate)
+ return mustProtect(((IRequestHandlerDelegate) handler).getDelegateHandler());
+ if (handler instanceof IPageClassRequestHandler)
{
- return value;
- }
-
- protected void checkValueForDirective(CSPRenderable value,
- List<CSPRenderable> existingDirectiveValues)
- {
- if (!existingDirectiveValues.isEmpty())
- {
- if (CSPDirectiveSrcValue.WILDCARD.equals(value)
- || CSPDirectiveSrcValue.NONE.equals(value))
- {
- throw new IllegalArgumentException(
- "A -src directive can't contain an * or a 'none' if it already contains other values ");
- }
- if (existingDirectiveValues.contains(CSPDirectiveSrcValue.WILDCARD)
- || existingDirectiveValues.contains(CSPDirectiveSrcValue.NONE))
- {
- throw new IllegalArgumentException(
- "A -src directive can't contain other values if it already contains an * or a 'none'");
- }
- }
-
- if (value instanceof CSPDirectiveSrcValue)
- {
- return;
- }
-
- if (value instanceof CSPDirectiveSandboxValue)
- {
- throw new IllegalArgumentException(
- "A -src directive can't contain any of the sandbox directive values");
- }
-
- String strValue = value.render(null, null);
- if ("data:".equals(strValue) || "https:".equals(strValue))
- {
- return;
- }
-
- // strip off "*." so "*.example.com" becomes "example.com" and we can check if
- // it
- // is a valid uri
- if (strValue.startsWith("*."))
- {
- strValue = strValue.substring(2);
- }
-
- try
- {
- new URI(strValue);
- }
- catch (URISyntaxException urise)
- {
- throw new IllegalArgumentException("Illegal URI for -src directive", urise);
- }
- }
-
- /**
- * @return The CSPDirective constant whose value-parameter equals the input-parameter or
- * {@code null} if none can be found.
- */
- public static CSPDirective fromValue(String value)
- {
- if (Strings.isEmpty(value))
- return null;
- for (int i = 0; i < values().length; i++)
- {
- if (value.equals(values()[i].getValue()))
- return values()[i];
- }
- return null;
+ return mustProtectPageRequest((IPageClassRequestHandler) handler);
}
+ return !(handler instanceof BufferedResponseRequestHandler);
}
-
- private enum CSPHeaderMode
- {
- BLOCKING("Content-Security-Policy"),
- REPORT_ONLY("Content-Security-Policy-Report-Only");
-
- private final String header;
-
- private CSPHeaderMode(String header)
- {
- this.header = header;
- }
-
- public String getHeader()
- {
- return header;
- }
-
- public String getLegacyHeader()
- {
- return "X-" + getHeader();
- }
- }
-
- public class CSPConfiguration
- {
- private CSPHeaderMode mode;
-
- private Map<CSPDirective, List<CSPRenderable>> directives =
- new EnumMap<>(CSPDirective.class);
-
- private boolean addLegacyHeaders = false;
-
- private CSPConfiguration(CSPHeaderMode mode)
- {
- this.mode = mode;
- }
-
- public CSPHeaderMode getMode()
- {
- return mode;
- }
-
- /**
- * True when legacy headers should be added.
- *
- * @return True when legacy headers should be added.
- */
- public boolean isAddLegacyHeaders()
- {
- return addLegacyHeaders;
- }
-
- /**
- * Enable legacy {@code X-Content-Security-Policy} headers for older browsers, such as IE.
- *
- * @param addLegacyHeaders
- * True when the legacy headers should be added.
- * @return {@code this} for chaining
- */
- public CSPConfiguration setAddLegacyHeaders(boolean addLegacyHeaders)
- {
- this.addLegacyHeaders = addLegacyHeaders;
- return this;
- }
-
- public CSPConfiguration addDirective(CSPDirective directive, CSPDirectiveSrcValue... values)
- {
- for (CSPDirectiveSrcValue value : values)
- {
- doAddDirective(directive, value);
- }
- return this;
- }
-
- /**
- * Adds any of the default values to the sandbox directive for the 'blocking' CSP header.
- * Use {@link #addBlockingDirective(CSPDirective, String...)} with the sandbox
- * {@link CSPDirective} and a single empty string (<em>not</em> {@code null}) to add the
- * empty sandbox directive.
- */
- public CSPConfiguration addDirective(CSPDirective sandboxDirective,
- CSPDirectiveSandboxValue... values)
- {
- for (CSPDirectiveSandboxValue value : values)
- {
- doAddDirective(sandboxDirective, value);
- }
- return this;
- }
-
- /**
- * Adds any value to a directive for the 'blocking' CSP header. Use
- * {@link #addBlockingDirective(CSPDirective, CSPDirectiveSandboxValue...)} and
- * {@link #addBlockingDirective(CSPDirective, CSPDirectiveSrcValue...)} for the default
- * values for the sandbox and -src directives.
- */
- public CSPConfiguration addDirective(CSPDirective directive, String... values)
- {
- for (String value : values)
- {
- doAddDirective(directive, new FixedCSPDirective(value));
- }
- return this;
- }
-
- public boolean isSet()
- {
- return !directives.isEmpty();
- }
-
- private CSPConfiguration doAddDirective(CSPDirective directive, CSPRenderable value)
- {
- // Add backwards compatible frame-src
- // see http://caniuse.com/#feat=contentsecuritypolicy2
- if (CSPDirective.CHILD_SRC.equals(directive))
- {
- doAddDirective(CSPDirective.FRAME_SRC, value);
- }
- List<CSPRenderable> values =
- directives.computeIfAbsent(directive, x -> new ArrayList<>());
- directive.checkValueForDirective(value, values);
- values.add(value);
- return this;
- }
-
- // @returns "key1 value1a value1b; key2 value2a; key3 value3a value3b value3c"
- public String renderHeaderValue(RequestCycle cycle)
- {
- return directives.entrySet()
- .stream()
- .map(e -> e.getKey().getValue() + " "
- + e.getValue()
- .stream()
- .map(r -> r.render(CSPSettingRequestCycleListener.this, cycle))
- .collect(Collectors.joining(" ")))
- .collect(Collectors.joining("; "));
- }
- }
-
- private Function<Integer, byte[]> randomSupplier;
-
- private Map<CSPHeaderMode, CSPConfiguration> configs = new HashMap<>();
-
- public CSPSettingRequestCycleListener()
- {
- }
-
- public CSPSettingRequestCycleListener(Function<Integer, byte[]> randomSupplier)
- {
- this.randomSupplier = randomSupplier;
- }
-
- public CSPConfiguration blocking()
- {
- return configs.computeIfAbsent(CSPHeaderMode.BLOCKING, CSPConfiguration::new);
- }
-
- public CSPConfiguration reporting()
- {
- return configs.computeIfAbsent(CSPHeaderMode.REPORT_ONLY, CSPConfiguration::new);
+
+ protected boolean mustProtectPageRequest(IPageClassRequestHandler handler) {
+ return true;
}
@Override
public void onRequestHandlerResolved(RequestCycle cycle, IRequestHandler handler)
{
+ if (!mustProtect(handler))
+ return;
+
WebResponse webResponse = (WebResponse) cycle.getResponse();
- configs.values().stream().filter(CSPConfiguration::isSet).forEach(config -> {
- String headerValue = config.renderHeaderValue(cycle);
- webResponse.setHeader(config.getMode().getHeader(), headerValue);
+ configs.entrySet().stream().filter(entry -> entry.getValue().isSet()).forEach(entry -> {
+ CSPHeaderMode mode = entry.getKey();
+ CSPHeaderConfiguration config = entry.getValue();
+ String headerValue = config.renderHeaderValue(this, cycle);
+ webResponse.setHeader(mode.getHeader(), headerValue);
if (config.isAddLegacyHeaders())
- webResponse.setHeader(config.getMode().getLegacyHeader(), headerValue);
+ webResponse.setHeader(mode.getLegacyHeader(), headerValue);
});
}
@@ -505,7 +130,7 @@ public class CSPSettingRequestCycleListener implements IRequestCycleListener
String nonce = cycle.getMetaData(NONCE_KEY);
if (nonce == null)
{
- nonce = Base64.getEncoder().encodeToString(randomSupplier.apply(12));
+ nonce = application.getSecuritySettings().getRandomSupplier().getRandomBase64(12);
cycle.setMetaData(NONCE_KEY, nonce);
}
return nonce;
diff --git a/wicket-core/src/main/java/org/apache/wicket/csp/FixedCSPDirective.java b/wicket-core/src/main/java/org/apache/wicket/csp/FixedCSPDirective.java
new file mode 100644
index 0000000..25886d6
--- /dev/null
+++ b/wicket-core/src/main/java/org/apache/wicket/csp/FixedCSPDirective.java
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.wicket.csp;
+
+import org.apache.wicket.request.cycle.RequestCycle;
+import org.apache.wicket.util.string.Strings;
+
+/**
+ * A simpel CSP directive that renders the string specified.
+ *
+ * @author papegaaij
+ */
+public class FixedCSPDirective implements CSPRenderable
+{
+ private String value;
+
+ /**
+ * Creates a new {@code FixedCSPDirective} for the given value.
+ *
+ * @param value
+ * the value to render;
+ */
+ public FixedCSPDirective(String value)
+ {
+ if (Strings.isEmpty(value))
+ throw new IllegalArgumentException(
+ "CSP directive cannot have empty or null values");
+ this.value = value;
+ }
+
+ @Override
+ public String render(CSPSettingRequestCycleListener listener, RequestCycle cycle)
+ {
+ return value;
+ }
+}
\ No newline at end of file
diff --git a/wicket-core/src/test/java/org/apache/wicket/csp/CSPSettingRequestCycleListenerTest.java b/wicket-core/src/test/java/org/apache/wicket/csp/CSPSettingRequestCycleListenerTest.java
index 14ba223..28b292c 100644
--- a/wicket-core/src/test/java/org/apache/wicket/csp/CSPSettingRequestCycleListenerTest.java
+++ b/wicket-core/src/test/java/org/apache/wicket/csp/CSPSettingRequestCycleListenerTest.java
@@ -16,16 +16,16 @@
*/
package org.apache.wicket.csp;
-import static org.apache.wicket.csp.CSPSettingRequestCycleListener.CSPDirective.CHILD_SRC;
-import static org.apache.wicket.csp.CSPSettingRequestCycleListener.CSPDirective.DEFAULT_SRC;
-import static org.apache.wicket.csp.CSPSettingRequestCycleListener.CSPDirective.FRAME_SRC;
-import static org.apache.wicket.csp.CSPSettingRequestCycleListener.CSPDirective.REPORT_URI;
-import static org.apache.wicket.csp.CSPSettingRequestCycleListener.CSPDirective.SANDBOX;
-import static org.apache.wicket.csp.CSPSettingRequestCycleListener.CSPDirectiveSandboxValue.ALLOW_FORMS;
-import static org.apache.wicket.csp.CSPSettingRequestCycleListener.CSPDirectiveSandboxValue.EMPTY;
-import static org.apache.wicket.csp.CSPSettingRequestCycleListener.CSPDirectiveSrcValue.NONE;
-import static org.apache.wicket.csp.CSPSettingRequestCycleListener.CSPDirectiveSrcValue.SELF;
-import static org.apache.wicket.csp.CSPSettingRequestCycleListener.CSPDirectiveSrcValue.WILDCARD;
+import static org.apache.wicket.csp.CSPDirective.CHILD_SRC;
+import static org.apache.wicket.csp.CSPDirective.DEFAULT_SRC;
+import static org.apache.wicket.csp.CSPDirective.FRAME_SRC;
+import static org.apache.wicket.csp.CSPDirective.REPORT_URI;
+import static org.apache.wicket.csp.CSPDirective.SANDBOX;
+import static org.apache.wicket.csp.CSPDirectiveSandboxValue.ALLOW_FORMS;
+import static org.apache.wicket.csp.CSPDirectiveSandboxValue.EMPTY;
+import static org.apache.wicket.csp.CSPDirectiveSrcValue.NONE;
+import static org.apache.wicket.csp.CSPDirectiveSrcValue.SELF;
+import static org.apache.wicket.csp.CSPDirectiveSrcValue.WILDCARD;
import java.net.URI;
import java.net.URISyntaxException;
@@ -37,9 +37,6 @@ import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
-import org.apache.wicket.csp.CSPSettingRequestCycleListener.CSPDirective;
-import org.apache.wicket.csp.CSPSettingRequestCycleListener.CSPDirectiveSandboxValue;
-import org.apache.wicket.csp.CSPSettingRequestCycleListener.CSPDirectiveSrcValue;
import org.apache.wicket.mock.MockHomePage;
import org.apache.wicket.util.tester.WicketTester;
import org.junit.jupiter.api.Assertions;
@@ -47,7 +44,7 @@ import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
@SuppressWarnings("deprecation")
-public class CSPSettingRequestCycleListenerTest
+public class CSPSettingRequestCycleListenerTest extends WicketTester
{
private static String HEADER_CSP = "Content-Security-Policy";
@@ -64,7 +61,8 @@ public class CSPSettingRequestCycleListenerTest
@Test
public void testNullSrcInputIsRejected()
{
- CSPSettingRequestCycleListener cspListener = new CSPSettingRequestCycleListener();
+ CSPSettingRequestCycleListener cspListener =
+ new CSPSettingRequestCycleListener(getApplication());
Assertions.assertThrows(IllegalArgumentException.class, () -> {
cspListener.blocking().addDirective(DEFAULT_SRC, (String) null);
});
@@ -73,7 +71,8 @@ public class CSPSettingRequestCycleListenerTest
@Test
public void testEmptySrcInputIsRejected()
{
- CSPSettingRequestCycleListener cspListener = new CSPSettingRequestCycleListener();
+ CSPSettingRequestCycleListener cspListener =
+ new CSPSettingRequestCycleListener(getApplication());
Assertions.assertThrows(IllegalArgumentException.class, () -> {
cspListener.blocking().addDirective(DEFAULT_SRC, "");
});
@@ -86,7 +85,8 @@ public class CSPSettingRequestCycleListenerTest
@Test
public void testInvalidSrcInputIsRejected()
{
- CSPSettingRequestCycleListener cspListener = new CSPSettingRequestCycleListener();
+ CSPSettingRequestCycleListener cspListener =
+ new CSPSettingRequestCycleListener(getApplication());
Assertions.assertThrows(IllegalArgumentException.class, () -> {
cspListener.blocking().addDirective(DEFAULT_SRC, "abc?^()-_\'xyz");
});
@@ -99,7 +99,8 @@ public class CSPSettingRequestCycleListenerTest
@Test
public void testMultipleSrcInputWithNoneIsRejected1()
{
- CSPSettingRequestCycleListener cspListener = new CSPSettingRequestCycleListener();
+ CSPSettingRequestCycleListener cspListener =
+ new CSPSettingRequestCycleListener(getApplication());
Assertions.assertThrows(IllegalArgumentException.class, () -> {
cspListener.blocking().addDirective(DEFAULT_SRC, SELF, NONE);
});
@@ -112,7 +113,8 @@ public class CSPSettingRequestCycleListenerTest
@Test
public void testMultipleSrcInputWithNoneIsRejected2()
{
- CSPSettingRequestCycleListener cspListener = new CSPSettingRequestCycleListener();
+ CSPSettingRequestCycleListener cspListener =
+ new CSPSettingRequestCycleListener(getApplication());
Assertions.assertThrows(IllegalArgumentException.class, () -> {
cspListener.blocking().addDirective(DEFAULT_SRC, NONE, SELF);
});
@@ -125,7 +127,8 @@ public class CSPSettingRequestCycleListenerTest
@Test
public void testMultipleSrcInputWithStarIsRejected1()
{
- CSPSettingRequestCycleListener cspListener = new CSPSettingRequestCycleListener();
+ CSPSettingRequestCycleListener cspListener =
+ new CSPSettingRequestCycleListener(getApplication());
cspListener.blocking().addDirective(DEFAULT_SRC, SELF);
Assertions.assertThrows(IllegalArgumentException.class, () -> {
cspListener.blocking().addDirective(DEFAULT_SRC, WILDCARD);
@@ -139,7 +142,8 @@ public class CSPSettingRequestCycleListenerTest
@Test
public void testMultipleSrcInputWithStarIsRejected2()
{
- CSPSettingRequestCycleListener cspListener = new CSPSettingRequestCycleListener();
+ CSPSettingRequestCycleListener cspListener =
+ new CSPSettingRequestCycleListener(getApplication());
cspListener.blocking().addDirective(DEFAULT_SRC, WILDCARD);
Assertions.assertThrows(IllegalArgumentException.class, () -> {
cspListener.blocking().addDirective(DEFAULT_SRC, SELF);
@@ -149,7 +153,8 @@ public class CSPSettingRequestCycleListenerTest
@Test
public void testWrongSrcInputIsRejected()
{
- CSPSettingRequestCycleListener cspListener = new CSPSettingRequestCycleListener();
+ CSPSettingRequestCycleListener cspListener =
+ new CSPSettingRequestCycleListener(getApplication());
Assertions.assertThrows(IllegalArgumentException.class, () -> {
cspListener.blocking().addDirective(DEFAULT_SRC, ALLOW_FORMS);
});
@@ -158,7 +163,8 @@ public class CSPSettingRequestCycleListenerTest
@Test
public void testWrongSandboxInputIsRejected()
{
- CSPSettingRequestCycleListener cspListener = new CSPSettingRequestCycleListener();
+ CSPSettingRequestCycleListener cspListener =
+ new CSPSettingRequestCycleListener(getApplication());
Assertions.assertThrows(IllegalArgumentException.class, () -> {
cspListener.blocking().addDirective(SANDBOX, SELF);
});
@@ -167,7 +173,8 @@ public class CSPSettingRequestCycleListenerTest
@Test
public void testNullSandboxInputIsRejected()
{
- CSPSettingRequestCycleListener cspListener = new CSPSettingRequestCycleListener();
+ CSPSettingRequestCycleListener cspListener =
+ new CSPSettingRequestCycleListener(getApplication());
Assertions.assertThrows(IllegalArgumentException.class, () -> {
cspListener.blocking().addDirective(SANDBOX, (String) null);
});
@@ -176,14 +183,16 @@ public class CSPSettingRequestCycleListenerTest
@Test
public void testEmptySandboxInputIsAccepted()
{
- CSPSettingRequestCycleListener cspListener = new CSPSettingRequestCycleListener();
+ CSPSettingRequestCycleListener cspListener =
+ new CSPSettingRequestCycleListener(getApplication());
cspListener.blocking().addDirective(SANDBOX, CSPDirectiveSandboxValue.EMPTY);
}
@Test
public void testInvalidSandboxInputIsRejected()
{
- CSPSettingRequestCycleListener cspListener = new CSPSettingRequestCycleListener();
+ CSPSettingRequestCycleListener cspListener =
+ new CSPSettingRequestCycleListener(getApplication());
Assertions.assertThrows(IllegalArgumentException.class, () -> {
cspListener.blocking().addDirective(SANDBOX, "abcxyz");
});
@@ -192,7 +201,8 @@ public class CSPSettingRequestCycleListenerTest
@Test
public void testMultipleSandboxInputWithEmptyStringIsRejected1()
{
- CSPSettingRequestCycleListener cspListener = new CSPSettingRequestCycleListener();
+ CSPSettingRequestCycleListener cspListener =
+ new CSPSettingRequestCycleListener(getApplication());
cspListener.blocking().addDirective(SANDBOX, ALLOW_FORMS);
Assertions.assertThrows(IllegalArgumentException.class, () -> {
cspListener.blocking().addDirective(SANDBOX, EMPTY);
@@ -202,7 +212,8 @@ public class CSPSettingRequestCycleListenerTest
@Test
public void testMultipleSandboxInputWithEmptyStringIsRejected2()
{
- CSPSettingRequestCycleListener cspListener = new CSPSettingRequestCycleListener();
+ CSPSettingRequestCycleListener cspListener =
+ new CSPSettingRequestCycleListener(getApplication());
cspListener.blocking().addDirective(SANDBOX, EMPTY);
Assertions.assertThrows(IllegalArgumentException.class, () -> {
cspListener.blocking().addDirective(SANDBOX, ALLOW_FORMS);
@@ -212,7 +223,8 @@ public class CSPSettingRequestCycleListenerTest
@Test
public void testNullReportUriInputIsRejected()
{
- CSPSettingRequestCycleListener cspListener = new CSPSettingRequestCycleListener();
+ CSPSettingRequestCycleListener cspListener =
+ new CSPSettingRequestCycleListener(getApplication());
Assertions.assertThrows(IllegalArgumentException.class, () -> {
cspListener.blocking().addDirective(REPORT_URI, (String) null);
});
@@ -221,7 +233,8 @@ public class CSPSettingRequestCycleListenerTest
@Test
public void testEmptyReportUriInputIsRejected()
{
- CSPSettingRequestCycleListener cspListener = new CSPSettingRequestCycleListener();
+ CSPSettingRequestCycleListener cspListener =
+ new CSPSettingRequestCycleListener(getApplication());
Assertions.assertThrows(IllegalArgumentException.class, () -> {
cspListener.blocking().addDirective(REPORT_URI, "");
});
@@ -230,7 +243,8 @@ public class CSPSettingRequestCycleListenerTest
@Test
public void testInvalidReportUriInputIsRejected()
{
- CSPSettingRequestCycleListener cspListener = new CSPSettingRequestCycleListener();
+ CSPSettingRequestCycleListener cspListener =
+ new CSPSettingRequestCycleListener(getApplication());
Assertions.assertThrows(IllegalArgumentException.class, () -> {
cspListener.blocking().addDirective(REPORT_URI, "abc?^()-_\'xyz");
});
@@ -239,12 +253,8 @@ public class CSPSettingRequestCycleListenerTest
@Test
public void testAllCSPSrcDefaultEnumsAreSetCorrectly() throws NoSuchAlgorithmException
{
- SecureRandom random = SecureRandom.getInstanceStrong();
- CSPSettingRequestCycleListener cspListener = new CSPSettingRequestCycleListener(length -> {
- byte[] ret = new byte[length];
- random.nextBytes(ret);
- return ret;
- });
+ CSPSettingRequestCycleListener cspListener =
+ new CSPSettingRequestCycleListener(getApplication());
final int cspDirectiveCount = CSPDirective.values().length;
final int cspDirectiveSrcValueCount = CSPDirectiveSrcValue.values().length;
@@ -273,7 +283,8 @@ public class CSPSettingRequestCycleListenerTest
@Test
public void testCSPReportUriDirectiveSetCorrectly()
{
- CSPSettingRequestCycleListener cspListener = new CSPSettingRequestCycleListener();
+ CSPSettingRequestCycleListener cspListener =
+ new CSPSettingRequestCycleListener(getApplication());
cspListener.blocking().addDirective(REPORT_URI, "http://report.example.com");
cspListener.reporting().addDirective(REPORT_URI, "/example-report-uri");
@@ -288,14 +299,15 @@ public class CSPSettingRequestCycleListenerTest
@Test
public void testCSPSandboxDirectiveSetCorrectly()
{
- CSPSettingRequestCycleListener cspListener = new CSPSettingRequestCycleListener();
+ CSPSettingRequestCycleListener cspListener =
+ new CSPSettingRequestCycleListener(getApplication());
final int cspSandboxDirectiveValueCount = CSPDirectiveSandboxValue.values().length;
for (int i = 0; i < cspSandboxDirectiveValueCount; i++)
{
final CSPDirectiveSandboxValue cspDirectiveValue = CSPDirectiveSandboxValue.values()[i];
if (cspDirectiveValue.equals(CSPDirectiveSandboxValue.EMPTY))
continue;
-
+
cspListener.blocking().addDirective(SANDBOX, cspDirectiveValue);
cspListener.reporting().addDirective(SANDBOX, cspDirectiveValue);
}
@@ -316,7 +328,8 @@ public class CSPSettingRequestCycleListenerTest
@Test
public void testChildSrcDirectiveAlsoSetsFrameSrcDirective()
{
- CSPSettingRequestCycleListener cspListener = new CSPSettingRequestCycleListener();
+ CSPSettingRequestCycleListener cspListener =
+ new CSPSettingRequestCycleListener(getApplication());
cspListener.blocking().addDirective(CHILD_SRC, SELF);
cspListener.reporting().addDirective(CHILD_SRC, SELF);
StringBuffer headerErrors = checkHeaders(cspListener);
@@ -460,5 +473,4 @@ public class CSPSettingRequestCycleListenerTest
return false;
}
-
}