From bed6ccd71921c9321919f7a042864dbbbf63243a Mon Sep 17 00:00:00 2001 From: Daniel Beck Date: Sat, 16 Dec 2017 22:16:37 +0100 Subject: [PATCH] Merge pull request #3187 from daniel-beck/JENKINS-34254-v2 [JENKINS-34254] Fix RequirePOST form (cherry picked from commit 76c9f8beacc681663571c925b5ee090222407e34) --- core/pom.xml | 2 +- .../hudson/security/csrf/CrumbFilter.java | 14 +++++++ .../security/csrf/CrumbFilter/retry.jelly | 42 +++++++++++++++++++ .../csrf/CrumbFilter/retry.properties | 4 ++ .../security/csrf/DefaultCrumbIssuerTest.java | 17 ++++++++ 5 files changed, 78 insertions(+), 1 deletion(-) create mode 100644 core/src/main/resources/hudson/security/csrf/CrumbFilter/retry.jelly create mode 100644 core/src/main/resources/hudson/security/csrf/CrumbFilter/retry.properties diff --git a/core/pom.xml b/core/pom.xml index b9345cd9b8..59eafcba6c 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -39,7 +39,7 @@ THE SOFTWARE. true - 1.253 + 1.254 2.5.6.SEC03 2.4.11 diff --git a/core/src/main/java/hudson/security/csrf/CrumbFilter.java b/core/src/main/java/hudson/security/csrf/CrumbFilter.java index e2b2790ef0..437d220952 100644 --- a/core/src/main/java/hudson/security/csrf/CrumbFilter.java +++ b/core/src/main/java/hudson/security/csrf/CrumbFilter.java @@ -8,6 +8,11 @@ package hudson.security.csrf; import hudson.util.MultipartFormDataParser; import jenkins.model.Jenkins; import org.acegisecurity.providers.anonymous.AnonymousAuthenticationToken; +import org.kohsuke.MetaInfServices; +import org.kohsuke.accmod.Restricted; +import org.kohsuke.accmod.restrictions.NoExternalUse; +import org.kohsuke.stapler.ForwardToView; +import org.kohsuke.stapler.interceptor.RequirePOST; import java.io.IOException; import java.util.Enumeration; @@ -41,6 +46,15 @@ public class CrumbFilter implements Filter { return h.getCrumbIssuer(); } + @Restricted(NoExternalUse.class) + @MetaInfServices + public static class ErrorCustomizer implements RequirePOST.ErrorCustomizer { + @Override + public ForwardToView getForwardView() { + return new ForwardToView(CrumbFilter.class, "retry"); + } + } + public void init(FilterConfig filterConfig) throws ServletException { } diff --git a/core/src/main/resources/hudson/security/csrf/CrumbFilter/retry.jelly b/core/src/main/resources/hudson/security/csrf/CrumbFilter/retry.jelly new file mode 100644 index 0000000000..70e615b78e --- /dev/null +++ b/core/src/main/resources/hudson/security/csrf/CrumbFilter/retry.jelly @@ -0,0 +1,42 @@ + + + + + + + + +

${%This URL requires POST}

+

+ ${%blurb} +

+

${requestURL}

+

${%warning}

+ + + +
+
+
diff --git a/core/src/main/resources/hudson/security/csrf/CrumbFilter/retry.properties b/core/src/main/resources/hudson/security/csrf/CrumbFilter/retry.properties new file mode 100644 index 0000000000..0e47fdc8d5 --- /dev/null +++ b/core/src/main/resources/hudson/security/csrf/CrumbFilter/retry.properties @@ -0,0 +1,4 @@ +blurb = The URL you're trying to access requires that requests be sent using POST (like a form submission). \ + The button below allows you to retry accessing this URL using POST. \ + URL being accessed: +warning = If you were sent here from an untrusted source, please proceed with caution. \ No newline at end of file diff --git a/test/src/test/java/hudson/security/csrf/DefaultCrumbIssuerTest.java b/test/src/test/java/hudson/security/csrf/DefaultCrumbIssuerTest.java index f3fddef1af..52dc455faf 100644 --- a/test/src/test/java/hudson/security/csrf/DefaultCrumbIssuerTest.java +++ b/test/src/test/java/hudson/security/csrf/DefaultCrumbIssuerTest.java @@ -8,6 +8,8 @@ package hudson.security.csrf; import com.gargoylesoftware.htmlunit.FailingHttpStatusCodeException; import com.gargoylesoftware.htmlunit.html.HtmlPage; +import jenkins.model.Jenkins; +import junit.framework.Assert; import net.sf.json.JSONObject; import org.junit.Before; import org.junit.Rule; @@ -135,4 +137,19 @@ public class DefaultCrumbIssuerTest { wc.assertFails("crumbIssuer/api/json?jsonp=hack", HttpURLConnection.HTTP_FORBIDDEN); } + @Issue("JENKINS-34254") + @Test public void testRequirePostErrorPageCrumb() throws Exception { + Jenkins.getInstance().setCrumbIssuer(new DefaultCrumbIssuer(false)); + WebClient wc = r.createWebClient(); + try { + wc.goTo("quietDown"); + fail("expected failure"); + } catch (FailingHttpStatusCodeException ex) { + Assert.assertEquals("expect HTTP 405 method not allowed", 405, ex.getStatusCode()); + } + HtmlPage retry = (HtmlPage) wc.getCurrentWindow().getEnclosedPage(); + HtmlPage success = r.submit(retry.getFormByName("retry")); + Assert.assertTrue("quieting down", r.jenkins.isQuietingDown()); + } + }