Started working on a HostFilter. Not yet complete.
git-svn-id: https://svn.apache.org/repos/asf/incubator/jsecurity/trunk@762587 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/core/src/main/java/org/apache/ki/util/RegExPatternMatcher.java b/core/src/main/java/org/apache/ki/util/RegExPatternMatcher.java
new file mode 100644
index 0000000..c7c4253
--- /dev/null
+++ b/core/src/main/java/org/apache/ki/util/RegExPatternMatcher.java
@@ -0,0 +1,53 @@
+/*
+ * 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.ki.util;
+
+import java.util.regex.Pattern;
+import java.util.regex.Matcher;
+
+/**
+ * {@code PatternMatcher} implementation that uses standard {@link java.util.regex} objects.
+ *
+ * @see Pattern
+ * @author Les Hazlewood
+ * @since 1.0
+ */
+public class RegExPatternMatcher implements PatternMatcher {
+
+ /**
+ * Simple implementation that merely uses the default pattern comparison logic provided by the
+ * JDK.
+ * <p/>This implementation essentially executes the following:
+ * <pre>
+ * Pattern p = Pattern.compile(pattern);
+ * Matcher m = p.matcher(source);
+ * return m.matches();</pre>
+ * @param pattern the pattern to match against
+ * @param source the source to match
+ * @return {@code true} if the source matches the required pattern, {@code false} otherwise.
+ */
+ public boolean matches(String pattern, String source) {
+ if (pattern == null) {
+ throw new IllegalArgumentException("pattern argument cannot be null.");
+ }
+ Pattern p = Pattern.compile(pattern);
+ Matcher m = p.matcher(source);
+ return m.matches();
+ }
+}
diff --git a/core/src/test/java/org/apache/ki/util/RegExPatternMatcherTest.java b/core/src/test/java/org/apache/ki/util/RegExPatternMatcherTest.java
new file mode 100644
index 0000000..704987d
--- /dev/null
+++ b/core/src/test/java/org/apache/ki/util/RegExPatternMatcherTest.java
@@ -0,0 +1,43 @@
+/*
+ * 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.ki.util;
+
+import org.junit.Test;
+import static org.junit.Assert.*;
+
+import java.util.regex.Pattern;
+
+/**
+ * Unit tests for the {@link RegExPatternMatcher}.
+ *
+ * @since 1.0
+ */
+public class RegExPatternMatcherTest {
+
+ @Test
+ public void testSimplePattern() {
+ PatternMatcher pm = new RegExPatternMatcher();
+ String pattern = "a*b";
+ String test = "aaaaaaab";
+ //not necessary for the test, but Idea performs auto validation when it sees this:
+ Pattern.compile(pattern);
+ assertTrue(pm.matches(pattern, test));
+ }
+
+}
diff --git a/web/src/main/java/org/apache/ki/web/filter/AccessControlFilter.java b/web/src/main/java/org/apache/ki/web/filter/AccessControlFilter.java
index f35ef30..386caa2 100644
--- a/web/src/main/java/org/apache/ki/web/filter/AccessControlFilter.java
+++ b/web/src/main/java/org/apache/ki/web/filter/AccessControlFilter.java
@@ -161,7 +161,6 @@
* @throws Exception if an error occurs.
*/
public boolean onPreHandle(ServletRequest request, ServletResponse response, Object mappedValue) throws Exception {
- //mapped value is ignored - not needed for most (if not all) authc Filters.
return isAccessAllowed(request, response, mappedValue) || onAccessDenied(request, response, mappedValue);
}
diff --git a/web/src/main/java/org/apache/ki/web/filter/authz/HostFilter.java b/web/src/main/java/org/apache/ki/web/filter/authz/HostFilter.java
new file mode 100644
index 0000000..8b59a79
--- /dev/null
+++ b/web/src/main/java/org/apache/ki/web/filter/authz/HostFilter.java
@@ -0,0 +1,106 @@
+/*
+ * 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.ki.web.filter.authz;
+
+import org.apache.ki.util.StringUtils;
+
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import java.util.regex.Pattern;
+import java.util.Map;
+
+/**
+ * A Filter that can allow or deny access based on the host that sent the request.
+ *
+ * <b>WARNING:</b> NOT YET FULLY IMPLEMENTED!!! Work in progress.
+ *
+ * @since 1.0
+ */
+public class HostFilter extends AuthorizationFilter {
+
+ public static final String IPV4_QUAD_REGEX = "(?:[0-9]|[1-9][0-9]|1[0-9][0-9]|2(?:[0-4][0-9]|5[0-5]))";
+
+ public static final String IPV4_REGEX = "(?:" + IPV4_QUAD_REGEX + "\\.){3}" + IPV4_QUAD_REGEX + "$";
+ public static final Pattern IPV4_PATTERN = Pattern.compile(IPV4_REGEX);
+
+ public static final String PRIVATE_CLASS_B_SUBSET = "(?:1[6-9]|2[0-9]|3[0-1])";
+
+ public static final String PRIVATE_CLASS_A_REGEX = "10\\.(?:" + IPV4_QUAD_REGEX + "\\.){2}" + IPV4_QUAD_REGEX + "$";
+
+ public static final String PRIVATE_CLASS_B_REGEX =
+ "172\\." + PRIVATE_CLASS_B_SUBSET + "\\." + IPV4_QUAD_REGEX + "\\." + IPV4_QUAD_REGEX + "$";
+
+ public static final String PRIVATE_CLASS_C_REGEX = "192\\.168\\." + IPV4_QUAD_REGEX + "\\." + IPV4_QUAD_REGEX + "$";
+
+ Map<String, String> authorizedIps; //user-configured IP (which can be wildcarded) to constructed regex mapping
+ Map<String, String> deniedIps;
+ Map<String, String> authorizedHostnames;
+ Map<String, String> deniedHostnames;
+
+
+ public void setAuthorizedHosts(String authorizedHosts) {
+ if (!StringUtils.hasText(authorizedHosts)) {
+ throw new IllegalArgumentException("authorizedHosts argument cannot be null or empty.");
+ }
+ String[] hosts = StringUtils.tokenizeToStringArray(authorizedHosts, ", \t");
+
+ for (String host : hosts) {
+ //replace any periods with \\. to ensure the regex works:
+ String periodsReplaced = host.replace(".", "\\.");
+ //check for IPv4:
+ String wildcardsReplaced = periodsReplaced.replace("*", IPV4_QUAD_REGEX);
+
+ if (IPV4_PATTERN.matcher(wildcardsReplaced).matches()) {
+ authorizedIps.put(host, wildcardsReplaced);
+ } else {
+
+ }
+
+
+ }
+
+ }
+
+ public void setDeniedHosts(String deniedHosts) {
+ if (!StringUtils.hasText(deniedHosts)) {
+ throw new IllegalArgumentException("deniedHosts argument cannot be null or empty.");
+ }
+ }
+
+ protected boolean isIpv4Candidate(String host) {
+ String[] quads = StringUtils.tokenizeToStringArray(host, ".");
+ if (quads == null || quads.length != 4) {
+ return false;
+ }
+ for (String quad : quads) {
+ if (!quad.equals("*")) {
+ try {
+ Integer.parseInt(quad);
+ } catch (NumberFormatException nfe) {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) throws Exception {
+ throw new UnsupportedOperationException("Not yet fully implemented!!!" );
+ }
+}
diff --git a/web/src/test/java/org/apache/ki/web/filter/authz/HostFilterTest.java b/web/src/test/java/org/apache/ki/web/filter/authz/HostFilterTest.java
new file mode 100644
index 0000000..91e7fcf
--- /dev/null
+++ b/web/src/test/java/org/apache/ki/web/filter/authz/HostFilterTest.java
@@ -0,0 +1,81 @@
+/*
+ * 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.ki.web.filter.authz;
+
+import org.junit.Test;
+import static org.junit.Assert.*;
+
+import java.util.regex.Pattern;
+
+/** @since 1.0 */
+public class HostFilterTest {
+
+ @Test
+ public void testPrivateClassC() {
+ Pattern p = Pattern.compile(HostFilter.PRIVATE_CLASS_C_REGEX);
+
+ String base = "192.168.";
+
+ for (int i = 0; i < 256; i++) {
+ String ibase = base + i;
+ for (int j = 0; j < 256; j++) {
+ String ip = ibase + "." + j;
+ assertTrue(p.matcher(ip).matches());
+ }
+ }
+ }
+
+ @Test
+ public void testPrivateClassB() {
+ Pattern p = Pattern.compile(HostFilter.PRIVATE_CLASS_B_REGEX);
+
+ String base = "172.";
+
+ for (int i = 16; i < 32; i++) {
+ String ibase = base + i;
+ for (int j = 0; j < 256; j++) {
+ String jBase = ibase + "." + j;
+ for (int k = 0; k < 256; k++) {
+ String ip = jBase + "." + k;
+ assertTrue(p.matcher(ip).matches());
+ }
+ }
+ }
+ }
+
+ /* Takes a long time (20+ seconds?) - only enable when testing explicitly:
+ @Test
+ public void testPrivateClassA() {
+ Pattern p = Pattern.compile(HostFilter.PRIVATE_CLASS_A_REGEX);
+
+ String base = "10.";
+
+ for (int i = 0; i < 256; i++) {
+ String ibase = base + i;
+ for (int j = 0; j < 256; j++) {
+ String jBase = ibase + "." + j;
+ for (int k = 0; k < 256; k++) {
+ String ip = jBase + "." + k;
+ assertTrue(p.matcher(ip).matches());
+ }
+ }
+ }
+ } */
+
+}