This is an automated email from the ASF dual-hosted git repository.
papegaaij pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/wicket.git
The following commit(s) were added to refs/heads/master by this push:
new 27aba85 WICKET-6813: frame-src should clone all values of child-src
if unset not just the first
27aba85 is described below
commit 27aba858ea2f1eeb177de2d35961eb939a7bacd6
Author: Emond Papegaaij <[email protected]>
AuthorDate: Mon Aug 10 14:20:50 2020 +0200
WICKET-6813: frame-src should clone all values of child-src if unset not
just the first
---
.../apache/wicket/csp/CSPHeaderConfiguration.java | 14 ++++-
.../java/org/apache/wicket/csp/ClonedCSPValue.java | 67 ++++++++++++++++++++++
.../csp/CSPSettingRequestCycleListenerTest.java | 32 +++++++++++
3 files changed, 112 insertions(+), 1 deletion(-)
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
index ac3a19f..0e3de21 100644
---
a/wicket-core/src/main/java/org/apache/wicket/csp/CSPHeaderConfiguration.java
+++
b/wicket-core/src/main/java/org/apache/wicket/csp/CSPHeaderConfiguration.java
@@ -34,6 +34,7 @@ import static
org.apache.wicket.csp.CSPDirectiveSrcValue.UNSAFE_EVAL;
import static org.apache.wicket.csp.CSPDirectiveSrcValue.UNSAFE_INLINE;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.EnumMap;
import java.util.List;
import java.util.Map;
@@ -262,6 +263,16 @@ public class CSPHeaderConfiguration
}
/**
+ * Returns an unmodifiable map of the directives set for this header.
+ *
+ * @return The directives set for this header.
+ */
+ public Map<CSPDirective, List<CSPRenderable>> getDirectives()
+ {
+ return Collections.unmodifiableMap(directives);
+ }
+
+ /**
* @return true if this {@code CSPHeaderConfiguration} has any
directives configured.
*/
public boolean isSet()
@@ -307,7 +318,8 @@ public class CSPHeaderConfiguration
if (CSPDirective.CHILD_SRC.equals(directive)
&& !directives.containsKey(CSPDirective.FRAME_SRC))
{
- doAddDirective(CSPDirective.FRAME_SRC, value);
+ doAddDirective(CSPDirective.FRAME_SRC,
+ new ClonedCSPValue(this,
CSPDirective.CHILD_SRC));
}
List<CSPRenderable> values =
directives.computeIfAbsent(directive, x -> new ArrayList<>());
directive.checkValueForDirective(value, values);
diff --git
a/wicket-core/src/main/java/org/apache/wicket/csp/ClonedCSPValue.java
b/wicket-core/src/main/java/org/apache/wicket/csp/ClonedCSPValue.java
new file mode 100644
index 0000000..bd8dcb7
--- /dev/null
+++ b/wicket-core/src/main/java/org/apache/wicket/csp/ClonedCSPValue.java
@@ -0,0 +1,67 @@
+/*
+ * 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.List;
+import java.util.stream.Collectors;
+
+import org.apache.wicket.request.cycle.RequestCycle;
+import org.apache.wicket.util.lang.Args;
+
+/**
+ * A CSP value that renders the same value as rendered for the specified
directive.
+ *
+ * @author papegaaij
+ */
+public class ClonedCSPValue implements CSPRenderable
+{
+ private final CSPHeaderConfiguration headerConfiguration;
+
+ private final CSPDirective sourceDirective;
+
+ /**
+ * Creates a new {@code ClonedCSPValue} for the given directive.
+ *
+ * @param headerConfiguration
+ * the header to clone from;
+ * @param sourceDirective
+ * the directive to clone;
+ */
+ public ClonedCSPValue(CSPHeaderConfiguration headerConfiguration,
CSPDirective sourceDirective)
+ {
+ this.headerConfiguration = Args.notNull(headerConfiguration,
"headerConfiguration");
+ this.sourceDirective = Args.notNull(sourceDirective,
"sourceDirective");
+ }
+
+ @Override
+ public String render(ContentSecurityPolicySettings settings,
RequestCycle cycle)
+ {
+ List<CSPRenderable> values =
headerConfiguration.getDirectives().get(sourceDirective);
+ if (values == null)
+ {
+ throw new IllegalStateException(
+ "CSP directive " + sourceDirective + " not set,
cannot clone its value.");
+ }
+ return values.stream().map(r -> r.render(settings,
cycle)).collect(Collectors.joining(" "));
+ }
+
+ @Override
+ public String toString()
+ {
+ return "clone(" + sourceDirective.getValue() + ")";
+ }
+}
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 25eb9d9..9679cbc 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
@@ -26,6 +26,7 @@ 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 static org.junit.jupiter.api.Assertions.assertEquals;
import java.net.URI;
import java.net.URISyntaxException;
@@ -38,6 +39,8 @@ import java.util.stream.Stream;
import org.apache.wicket.mock.MockHomePage;
import org.apache.wicket.protocol.http.WebApplication;
+import org.apache.wicket.request.cycle.RequestCycle;
+import org.apache.wicket.util.tester.DummyHomePage;
import org.apache.wicket.util.tester.WicketTestCase;
import org.apache.wicket.util.tester.WicketTester;
import org.junit.jupiter.api.Assertions;
@@ -311,6 +314,35 @@ public class CSPSettingRequestCycleListenerTest extends
WicketTestCase
}
}
+ @Test
+ public void testChildIsClonedIntoFrame()
+ {
+ ContentSecurityPolicySettings settings =
tester.getApplication().getCspSettings();
+ settings.blocking().add(CHILD_SRC, SELF);
+
+ tester.startPage(DummyHomePage.class);
+ String childSrc =
renderDirective(settings.blocking().getDirectives().get(CHILD_SRC),
+ settings, tester.getRequestCycle());
+ String frameSrc =
renderDirective(settings.blocking().getDirectives().get(FRAME_SRC),
+ settings, tester.getRequestCycle());
+ assertEquals("'self'", childSrc);
+ assertEquals(childSrc, frameSrc);
+
+ settings.blocking().add(CHILD_SRC, "https://wicket.apache.org");
+ childSrc =
renderDirective(settings.blocking().getDirectives().get(CHILD_SRC), settings,
+ tester.getRequestCycle());
+ frameSrc =
renderDirective(settings.blocking().getDirectives().get(FRAME_SRC), settings,
+ tester.getRequestCycle());
+ assertEquals("'self' https://wicket.apache.org", childSrc);
+ assertEquals(childSrc, frameSrc);
+ }
+
+ private String renderDirective(List<CSPRenderable> values,
+ ContentSecurityPolicySettings settings, RequestCycle cycle)
+ {
+ return values.stream().map(r -> r.render(settings,
cycle)).collect(Collectors.joining(" "));
+ }
+
private List<String> checkHeaders()
{
List<String> headerErrors = new ArrayList<>();