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<>();

Reply via email to