From 80ff9857f005e89350848b1a2e5c22766615de32 Mon Sep 17 00:00:00 2001 From: John Gasper Date: Wed, 5 Mar 2014 10:17:59 -0800 Subject: [PATCH 1/6] Added support for having regex expressions in the proxy (chaining) list. --- .../cas/client/validation/ProxyList.java | 19 +++++++++++ .../Cas20ProxyTicketValidatorTests.java | 32 +++++++++++++++++++ 2 files changed, 51 insertions(+) diff --git a/cas-client-core/src/main/java/org/jasig/cas/client/validation/ProxyList.java b/cas-client-core/src/main/java/org/jasig/cas/client/validation/ProxyList.java index 3585d5b..7baaa56 100644 --- a/cas-client-core/src/main/java/org/jasig/cas/client/validation/ProxyList.java +++ b/cas-client-core/src/main/java/org/jasig/cas/client/validation/ProxyList.java @@ -27,6 +27,7 @@ import org.jasig.cas.client.util.CommonUtils; * Holding class for the proxy list to make Spring configuration easier. * * @author Scott Battaglia + * @author John Gasper * @version $Revision$ $Date$ * @since 3.1.3 */ @@ -47,6 +48,24 @@ public final class ProxyList { for (final String[] list : this.proxyChains) { if (Arrays.equals(proxiedList, list)) { return true; + } else { + //strings might be regex, so check for each string + if (list.length == proxiedList.length) { + boolean passed = false; + + for (int i=0; i list = new ArrayList(); + list.add(new String[] { "proxy1", "proxy2", "^proxy3/[a-z]*/" }); + this.ticketValidator.setAllowedProxyChains(new ProxyList(list)); + + final String USERNAME = "username"; + final String RESPONSE = "usernamePGTIOU-84678-8a9d...proxy1proxy2proxy3/abc/"; + server.content = RESPONSE.getBytes(server.encoding); + + final Assertion assertion = this.ticketValidator.validate("test", "test"); + assertEquals(USERNAME, assertion.getPrincipal().getName()); + } + + @Test + public void testRegexProxyChainWithInvalidProxy() throws TicketValidationException, UnsupportedEncodingException { + final List list = new ArrayList(); + list.add(new String[] { "proxy1", "proxy2", "^proxy3/[a-z]*/" }); + this.ticketValidator.setAllowedProxyChains(new ProxyList(list)); + + final String RESPONSE = "usernamePGTIOU-84678-8a9d...proxy/ABC/proxy2proxy3"; + server.content = RESPONSE.getBytes(server.encoding); + + try { + this.ticketValidator.validate("test", "test"); + fail("Invalid proxy chain"); + } catch (InvalidProxyChainTicketValidationException e) { + // expected + } + } + @Test public void testConstructionFromSpringBean() throws TicketValidationException, UnsupportedEncodingException { final ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext( From 90ccc41db3023a30613dbb87bdad9c12eec1e436 Mon Sep 17 00:00:00 2001 From: John Gasper Date: Wed, 5 Mar 2014 10:45:35 -0800 Subject: [PATCH 2/6] Minor corrections. --- .../main/java/org/jasig/cas/client/validation/ProxyList.java | 2 +- .../cas/client/validation/Cas20ProxyTicketValidatorTests.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cas-client-core/src/main/java/org/jasig/cas/client/validation/ProxyList.java b/cas-client-core/src/main/java/org/jasig/cas/client/validation/ProxyList.java index 7baaa56..aef87d0 100644 --- a/cas-client-core/src/main/java/org/jasig/cas/client/validation/ProxyList.java +++ b/cas-client-core/src/main/java/org/jasig/cas/client/validation/ProxyList.java @@ -27,7 +27,6 @@ import org.jasig.cas.client.util.CommonUtils; * Holding class for the proxy list to make Spring configuration easier. * * @author Scott Battaglia - * @author John Gasper * @version $Revision$ $Date$ * @since 3.1.3 */ @@ -59,6 +58,7 @@ public final class ProxyList { || pattern.equals(proxiedList[i])) { passed = true; } else { + passed = false; break; } } diff --git a/cas-client-core/src/test/java/org/jasig/cas/client/validation/Cas20ProxyTicketValidatorTests.java b/cas-client-core/src/test/java/org/jasig/cas/client/validation/Cas20ProxyTicketValidatorTests.java index 234bb9d..44c2f41 100644 --- a/cas-client-core/src/test/java/org/jasig/cas/client/validation/Cas20ProxyTicketValidatorTests.java +++ b/cas-client-core/src/test/java/org/jasig/cas/client/validation/Cas20ProxyTicketValidatorTests.java @@ -126,7 +126,7 @@ public final class Cas20ProxyTicketValidatorTests extends AbstractTicketValidato list.add(new String[] { "proxy1", "proxy2", "^proxy3/[a-z]*/" }); this.ticketValidator.setAllowedProxyChains(new ProxyList(list)); - final String RESPONSE = "usernamePGTIOU-84678-8a9d...proxy/ABC/proxy2proxy3"; + final String RESPONSE = "usernamePGTIOU-84678-8a9d...proxy1proxy2proxy3/ABC/"; server.content = RESPONSE.getBytes(server.encoding); try { From 887da3bffda88c2b6e34fe9ebfc791f3e1473b31 Mon Sep 17 00:00:00 2001 From: John Gasper Date: Wed, 5 Mar 2014 10:54:34 -0800 Subject: [PATCH 3/6] no message --- .../cas/client/validation/Cas20ProxyTicketValidatorTests.java | 1 - 1 file changed, 1 deletion(-) diff --git a/cas-client-core/src/test/java/org/jasig/cas/client/validation/Cas20ProxyTicketValidatorTests.java b/cas-client-core/src/test/java/org/jasig/cas/client/validation/Cas20ProxyTicketValidatorTests.java index 44c2f41..b0db574 100644 --- a/cas-client-core/src/test/java/org/jasig/cas/client/validation/Cas20ProxyTicketValidatorTests.java +++ b/cas-client-core/src/test/java/org/jasig/cas/client/validation/Cas20ProxyTicketValidatorTests.java @@ -35,7 +35,6 @@ import org.springframework.context.support.ClassPathXmlApplicationContext; * Test cases for the {@link Cas20ProxyTicketValidator}. * * @author Scott Battaglia - * @author John Gasper * @version $Revision: 11737 $ $Date: 2007-10-03 09:14:02 -0400 (Tue, 03 Oct 2007) $ * @since 3.0 */ From 0ef575ae842bde39c881196f81236a7c93f05f2a Mon Sep 17 00:00:00 2001 From: John Gasper Date: Fri, 7 Mar 2014 16:11:00 -0800 Subject: [PATCH 4/6] Refactored the match logic and cache the regex patterns. --- .../cas/client/validation/ProxyList.java | 48 +++++++++++-------- 1 file changed, 28 insertions(+), 20 deletions(-) diff --git a/cas-client-core/src/main/java/org/jasig/cas/client/validation/ProxyList.java b/cas-client-core/src/main/java/org/jasig/cas/client/validation/ProxyList.java index aef87d0..3a6846c 100644 --- a/cas-client-core/src/main/java/org/jasig/cas/client/validation/ProxyList.java +++ b/cas-client-core/src/main/java/org/jasig/cas/client/validation/ProxyList.java @@ -19,8 +19,9 @@ package org.jasig.cas.client.validation; import java.util.ArrayList; -import java.util.Arrays; +import java.util.HashMap; import java.util.List; +import java.util.regex.Pattern; import org.jasig.cas.client.util.CommonUtils; /** @@ -33,10 +34,20 @@ import org.jasig.cas.client.util.CommonUtils; public final class ProxyList { private final List proxyChains; + private final HashMap proxyChainRegexCache; public ProxyList(final List proxyChains) { CommonUtils.assertNotNull(proxyChains, "List of proxy chains cannot be null."); this.proxyChains = proxyChains; + + this.proxyChainRegexCache = new HashMap(); + for (final String[] list : this.proxyChains) { + for (final String item : list) { + if (item.startsWith("^")) { + this.proxyChainRegexCache.put(item, Pattern.compile(item)); + } + } + } } public ProxyList() { @@ -44,26 +55,23 @@ public final class ProxyList { } public boolean contains(String[] proxiedList) { - for (final String[] list : this.proxyChains) { - if (Arrays.equals(proxiedList, list)) { - return true; - } else { - //strings might be regex, so check for each string - if (list.length == proxiedList.length) { - boolean passed = false; - - for (int i=0; i Date: Mon, 14 Apr 2014 08:45:21 -0700 Subject: [PATCH 5/6] Using Misagh's PatternMatcherStrategy to optimize proxy chain checks --- .../ExactUrlPatternMatcherStrategy.java | 8 +++- .../RegexUrlPatternMatcherStrategy.java | 6 +++ .../cas/client/validation/ProxyList.java | 48 ++++++++++++------- 3 files changed, 45 insertions(+), 17 deletions(-) diff --git a/cas-client-core/src/main/java/org/jasig/cas/client/authentication/ExactUrlPatternMatcherStrategy.java b/cas-client-core/src/main/java/org/jasig/cas/client/authentication/ExactUrlPatternMatcherStrategy.java index 64f20eb..9fd0ddf 100644 --- a/cas-client-core/src/main/java/org/jasig/cas/client/authentication/ExactUrlPatternMatcherStrategy.java +++ b/cas-client-core/src/main/java/org/jasig/cas/client/authentication/ExactUrlPatternMatcherStrategy.java @@ -28,7 +28,13 @@ package org.jasig.cas.client.authentication; public final class ExactUrlPatternMatcherStrategy implements UrlPatternMatcherStrategy { private String pattern; - + + public ExactUrlPatternMatcherStrategy() {} + + public ExactUrlPatternMatcherStrategy(final String pattern) { + this.setPattern(pattern); + } + public boolean matches(final String url) { return url.equals(this.pattern); } diff --git a/cas-client-core/src/main/java/org/jasig/cas/client/authentication/RegexUrlPatternMatcherStrategy.java b/cas-client-core/src/main/java/org/jasig/cas/client/authentication/RegexUrlPatternMatcherStrategy.java index a941459..e5665cd 100644 --- a/cas-client-core/src/main/java/org/jasig/cas/client/authentication/RegexUrlPatternMatcherStrategy.java +++ b/cas-client-core/src/main/java/org/jasig/cas/client/authentication/RegexUrlPatternMatcherStrategy.java @@ -30,6 +30,12 @@ import java.util.regex.Pattern; public final class RegexUrlPatternMatcherStrategy implements UrlPatternMatcherStrategy { private Pattern pattern; + + public RegexUrlPatternMatcherStrategy() {} + + public RegexUrlPatternMatcherStrategy(final String pattern) { + this.setPattern(pattern); + } public boolean matches(final String url) { return this.pattern.matcher(url).find(); diff --git a/cas-client-core/src/main/java/org/jasig/cas/client/validation/ProxyList.java b/cas-client-core/src/main/java/org/jasig/cas/client/validation/ProxyList.java index 3a6846c..606923c 100644 --- a/cas-client-core/src/main/java/org/jasig/cas/client/validation/ProxyList.java +++ b/cas-client-core/src/main/java/org/jasig/cas/client/validation/ProxyList.java @@ -19,10 +19,13 @@ package org.jasig.cas.client.validation; import java.util.ArrayList; -import java.util.HashMap; import java.util.List; -import java.util.regex.Pattern; +import org.jasig.cas.client.authentication.ExactUrlPatternMatcherStrategy; +import org.jasig.cas.client.authentication.RegexUrlPatternMatcherStrategy; +import org.jasig.cas.client.authentication.UrlPatternMatcherStrategy; import org.jasig.cas.client.util.CommonUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * Holding class for the proxy list to make Spring configuration easier. @@ -33,20 +36,28 @@ import org.jasig.cas.client.util.CommonUtils; */ public final class ProxyList { - private final List proxyChains; - private final HashMap proxyChainRegexCache; + private final Logger logger = LoggerFactory.getLogger(getClass()); + + private final List> proxyChains; public ProxyList(final List proxyChains) { CommonUtils.assertNotNull(proxyChains, "List of proxy chains cannot be null."); - this.proxyChains = proxyChains; - this.proxyChainRegexCache = new HashMap(); - for (final String[] list : this.proxyChains) { + this.proxyChains = new ArrayList>(); + + for (final String[] list : proxyChains) { + final List chain = new ArrayList(); + for (final String item : list) { if (item.startsWith("^")) { - this.proxyChainRegexCache.put(item, Pattern.compile(item)); + chain.add(new RegexUrlPatternMatcherStrategy(item)); + } + else { + chain.add(new ExactUrlPatternMatcherStrategy(item)); } } + + this.proxyChains.add(chain); } } @@ -55,28 +66,33 @@ public final class ProxyList { } public boolean contains(String[] proxiedList) { - for (final String[] proxyChain : this.proxyChains) { + StringBuilder loggingOutput; - if (proxyChain.length == proxiedList.length) { + for (final List proxyChain : this.proxyChains) { + loggingOutput = new StringBuilder(); - for (int linkIndex = 0; linkIndex < proxyChain.length; linkIndex++) { - String link = proxyChain[linkIndex]; - - if (link.equals(proxiedList[linkIndex]) - || (link.startsWith("^") && proxyChainRegexCache.get(link).matcher(proxiedList[linkIndex]).matches())) { + if (proxyChain.size() == proxiedList.length) { + for (int linkIndex = 0; linkIndex < proxyChain.size(); linkIndex++) { + final String linkToTest = proxiedList[linkIndex]; + loggingOutput.append(linkToTest); + if (proxyChain.get(linkIndex).matches(linkToTest)) { //If we are at the last link, we found a good proxyChain. - if (linkIndex == proxyChain.length-1) { + if (linkIndex == proxyChain.size()-1) { + logger.info("Proxy chain matched: {}", loggingOutput.toString()); return true; } } else { + logger.warn("Proxy chain did not match at {}. Skipping to next allowedProxyChain", loggingOutput.toString()); break; } + loggingOutput.append("->"); } } } + logger.warn("No proxy chain matched the allowedProxyChains list."); return false; } From c61dea96bfe4d6b227b2f83c1044659a950d33f7 Mon Sep 17 00:00:00 2001 From: John Gasper Date: Tue, 15 Apr 2014 12:56:46 -0700 Subject: [PATCH 6/6] Formatting clean-up --- .../main/java/org/jasig/cas/client/validation/ProxyList.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/cas-client-core/src/main/java/org/jasig/cas/client/validation/ProxyList.java b/cas-client-core/src/main/java/org/jasig/cas/client/validation/ProxyList.java index 606923c..a15a62b 100644 --- a/cas-client-core/src/main/java/org/jasig/cas/client/validation/ProxyList.java +++ b/cas-client-core/src/main/java/org/jasig/cas/client/validation/ProxyList.java @@ -51,8 +51,7 @@ public final class ProxyList { for (final String item : list) { if (item.startsWith("^")) { chain.add(new RegexUrlPatternMatcherStrategy(item)); - } - else { + } else { chain.add(new ExactUrlPatternMatcherStrategy(item)); } } @@ -78,7 +77,7 @@ public final class ProxyList { if (proxyChain.get(linkIndex).matches(linkToTest)) { //If we are at the last link, we found a good proxyChain. - if (linkIndex == proxyChain.size()-1) { + if (linkIndex == proxyChain.size() - 1) { logger.info("Proxy chain matched: {}", loggingOutput.toString()); return true; }