From 253b0c8be2a85b3fe8a27728f722a4171dbbcaaa Mon Sep 17 00:00:00 2001 From: kel Date: Sat, 9 Sep 2017 22:44:07 +0800 Subject: [PATCH] [Fix JENKINS-44663] Make Basic authorization header to be case in-sensitive (#3002) [Fix JENKINS-44663] Make Basic authorization header to be case in-sensitive --- .../security/BasicHeaderProcessor.java | 3 +- .../security/BasicHeaderProcessorTest.java | 51 +++++++++++++++++-- 2 files changed, 49 insertions(+), 5 deletions(-) diff --git a/core/src/main/java/jenkins/security/BasicHeaderProcessor.java b/core/src/main/java/jenkins/security/BasicHeaderProcessor.java index 243e044acb..df176b0a1b 100644 --- a/core/src/main/java/jenkins/security/BasicHeaderProcessor.java +++ b/core/src/main/java/jenkins/security/BasicHeaderProcessor.java @@ -12,6 +12,7 @@ import org.acegisecurity.providers.anonymous.AnonymousAuthenticationToken; import org.acegisecurity.ui.AuthenticationEntryPoint; import org.acegisecurity.ui.rememberme.NullRememberMeServices; import org.acegisecurity.ui.rememberme.RememberMeServices; +import org.apache.commons.lang.StringUtils; import javax.servlet.Filter; import javax.servlet.FilterChain; @@ -60,7 +61,7 @@ public class BasicHeaderProcessor implements Filter { HttpServletResponse rsp = (HttpServletResponse) response; String authorization = req.getHeader("Authorization"); - if (authorization!=null && authorization.startsWith("Basic ")) { + if (StringUtils.startsWithIgnoreCase(authorization,"Basic ")) { // authenticate the user String uidpassword = Scrambler.descramble(authorization.substring(6)); int idx = uidpassword.indexOf(':'); diff --git a/test/src/test/java/jenkins/security/BasicHeaderProcessorTest.java b/test/src/test/java/jenkins/security/BasicHeaderProcessorTest.java index 9b334db55e..449293ae10 100644 --- a/test/src/test/java/jenkins/security/BasicHeaderProcessorTest.java +++ b/test/src/test/java/jenkins/security/BasicHeaderProcessorTest.java @@ -72,8 +72,19 @@ public class BasicHeaderProcessorTest { } private void makeRequestAndFail(String userAndPass) throws IOException, SAXException { + makeRequestWithAuthCodeAndFail(encrypt("Basic", userAndPass)); + } + + private String encrypt(String prefix, String userAndPass) { + if (userAndPass==null) { + return null; + } + return prefix+" "+Scrambler.scramble(userAndPass); + } + + private void makeRequestWithAuthCodeAndFail(String authCode) throws IOException, SAXException { try { - makeRequestWithAuthAndVerify(userAndPass, "-"); + makeRequestWithAuthCodeAndVerify(authCode, "-"); fail(); } catch (FailingHttpStatusCodeException e) { assertEquals(401, e.getStatusCode()); @@ -81,13 +92,45 @@ public class BasicHeaderProcessorTest { } private void makeRequestWithAuthAndVerify(String userAndPass, String username) throws IOException, SAXException { + makeRequestWithAuthCodeAndVerify(encrypt("Basic", userAndPass), username); + } + + private void makeRequestWithAuthCodeAndVerify(String authCode, String expected) throws IOException, SAXException { WebRequest req = new WebRequest(new URL(j.getURL(),"test")); req.setEncodingType(null); - if (userAndPass!=null) - req.setAdditionalHeader("Authorization","Basic "+Scrambler.scramble(userAndPass)); + if (authCode!=null) + req.setAdditionalHeader("Authorization", authCode); Page p = wc.getPage(req); + assertEquals(expected, p.getWebResponse().getContentAsString().trim()); + } - assertEquals(username, p.getWebResponse().getContentAsString().trim()); + @Test + public void testAuthHeaderCaseInSensitive() throws Exception { + j.jenkins.setSecurityRealm(j.createDummySecurityRealm()); + User foo = User.get("foo"); + wc = j.createWebClient(); + + String[] basicCandidates = {"Basic", "BASIC", "basic", "bASIC"}; + + for (String prefix : basicCandidates) { + // call with API token + ApiTokenProperty t = foo.getProperty(ApiTokenProperty.class); + final String token = t.getApiToken(); + String authCode1 = encrypt(prefix,"foo:"+token); + makeRequestWithAuthCodeAndVerify(authCode1, "foo"); + + // call with invalid API token + String authCode2 = encrypt(prefix,"foo:abcd"+token); + makeRequestWithAuthCodeAndFail(authCode2); + + // call with password + String authCode3 = encrypt(prefix,"foo:foo"); + makeRequestWithAuthCodeAndVerify(authCode3, "foo"); + + // call with incorrect password + String authCode4 = encrypt(prefix,"foo:bar"); + makeRequestWithAuthCodeAndFail(authCode4); + } } @TestExtension