mirror of
https://github.com/spring-projects/spring-security.git
synced 2026-01-08 15:36:44 +00:00
SEC-1033: Added support for web IP ranges based on an address and netmask.
This commit is contained in:
parent
7767a9ed60
commit
7fe6a0fc0d
@ -2,6 +2,7 @@ package org.springframework.security.expression.support;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.springframework.security.Authentication;
|
||||
import org.springframework.security.intercept.web.FilterInvocation;
|
||||
@ -21,33 +22,64 @@ class WebSecurityExpressionRoot extends SecurityExpressionRoot {
|
||||
this.filterInvocation = fi;
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes a specific IP address or a range using the IP/Netmask (e.g. 192.168.1.0/24 or 202.24.0.0/14).
|
||||
*
|
||||
* @param ipAddress the address or range of addresses from which the request must come.
|
||||
* @return true if the IP address of the current request is in the required range.
|
||||
*/
|
||||
public boolean hasIpAddress(String ipAddress) {
|
||||
byte[] mask = null;
|
||||
int nMaskBits = 0;
|
||||
|
||||
if (ipAddress.indexOf('/') > 0) {
|
||||
String[] addressAndMask = StringUtils.split(ipAddress, "/");
|
||||
ipAddress = addressAndMask[0];
|
||||
try {
|
||||
mask = InetAddress.getByName(addressAndMask[1]).getAddress();
|
||||
} catch (UnknownHostException e) {
|
||||
throw new IllegalArgumentException("Failed to parse mask" + addressAndMask[1], e);
|
||||
nMaskBits = Integer.parseInt(addressAndMask[1]);
|
||||
}
|
||||
|
||||
InetAddress requiredAddress = parseAddress(ipAddress);
|
||||
InetAddress remoteAddress = parseAddress(filterInvocation.getHttpRequest().getRemoteAddr());
|
||||
|
||||
if (!requiredAddress.getClass().equals(remoteAddress.getClass())) {
|
||||
throw new IllegalArgumentException("IP Address in expression must be the same type as " +
|
||||
"version returned by request");
|
||||
}
|
||||
|
||||
if (nMaskBits == 0) {
|
||||
return remoteAddress.equals(requiredAddress);
|
||||
}
|
||||
|
||||
byte[] remAddr = remoteAddress.getAddress();
|
||||
byte[] reqAddr = requiredAddress.getAddress();
|
||||
|
||||
int oddBits = nMaskBits % 8;
|
||||
int nMaskBytes = nMaskBits/8 + (oddBits == 0 ? 0 : 1);
|
||||
byte[] mask = new byte[nMaskBytes];
|
||||
|
||||
Arrays.fill(mask, 0, oddBits == 0 ? mask.length : mask.length - 1, (byte)0xFF);
|
||||
|
||||
if (oddBits != 0) {
|
||||
int finalByte = (1 << oddBits) - 1;
|
||||
finalByte <<= 8-oddBits;
|
||||
mask[mask.length - 1] = (byte) finalByte;
|
||||
}
|
||||
|
||||
// System.out.println("Mask is " + new sun.misc.HexDumpEncoder().encode(mask));
|
||||
|
||||
for (int i=0; i < mask.length; i++) {
|
||||
if ((remAddr[i] & mask[i]) != (reqAddr[i] & mask[i])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private InetAddress parseAddress(String address) {
|
||||
try {
|
||||
InetAddress requiredAddress = InetAddress.getByName(ipAddress);
|
||||
InetAddress remoteAddress = InetAddress.getByName(filterInvocation.getHttpRequest().getRemoteAddr());
|
||||
|
||||
if (mask == null) {
|
||||
return remoteAddress.equals(requiredAddress);
|
||||
} else {
|
||||
|
||||
}
|
||||
// byte[] remoteAddress = InetAddress.getByName(filterInvocation.getHttpRequest().getRemoteAddr()).getAddress();
|
||||
return InetAddress.getByName(address);
|
||||
} catch (UnknownHostException e) {
|
||||
throw new IllegalArgumentException("Failed to parse " + ipAddress, e);
|
||||
throw new IllegalArgumentException("Failed to parse address" + address, e);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@ -10,6 +10,13 @@ import org.springframework.security.Authentication;
|
||||
import org.springframework.security.intercept.web.FilterInvocation;
|
||||
import org.springframework.security.util.FilterInvocationUtils;
|
||||
|
||||
/**
|
||||
* Tests for {@link WebSecurityExpressionRoot}.
|
||||
*
|
||||
* @author Luke Taylor
|
||||
* @version $Id$
|
||||
* @since 2.5
|
||||
*/
|
||||
public class WebSecurityExpressionRootTests {
|
||||
Mockery jmock = new JUnit4Mockery();
|
||||
|
||||
@ -17,9 +24,46 @@ public class WebSecurityExpressionRootTests {
|
||||
public void ipAddressMatchesForEqualIpAddresses() throws Exception {
|
||||
FilterInvocation fi = FilterInvocationUtils.create("/test");
|
||||
MockHttpServletRequest request = (MockHttpServletRequest) fi.getHttpRequest();
|
||||
// IPv4
|
||||
request.setRemoteAddr("192.168.1.1");
|
||||
WebSecurityExpressionRoot root = new WebSecurityExpressionRoot(jmock.mock(Authentication.class), fi);
|
||||
|
||||
assertTrue(root.hasIpAddress("192.168.1.1"));
|
||||
|
||||
// IPv6 Address
|
||||
request.setRemoteAddr("fa:db8:85a3::8a2e:370:7334");
|
||||
assertTrue(root.hasIpAddress("fa:db8:85a3::8a2e:370:7334"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void addressesInIpRangeMatch() throws Exception {
|
||||
FilterInvocation fi = FilterInvocationUtils.create("/test");
|
||||
MockHttpServletRequest request = (MockHttpServletRequest) fi.getHttpRequest();
|
||||
WebSecurityExpressionRoot root = new WebSecurityExpressionRoot(jmock.mock(Authentication.class), fi);
|
||||
for (int i=0; i < 255; i++) {
|
||||
request.setRemoteAddr("192.168.1." + i);
|
||||
assertTrue(root.hasIpAddress("192.168.1.0/24"));
|
||||
}
|
||||
|
||||
request.setRemoteAddr("192.168.1.127");
|
||||
// 25 = FF FF FF 80
|
||||
assertTrue(root.hasIpAddress("192.168.1.0/25"));
|
||||
// encroach on the mask
|
||||
request.setRemoteAddr("192.168.1.128");
|
||||
assertFalse(root.hasIpAddress("192.168.1.0/25"));
|
||||
request.setRemoteAddr("192.168.1.255");
|
||||
assertTrue(root.hasIpAddress("192.168.1.128/25"));
|
||||
assertTrue(root.hasIpAddress("192.168.1.192/26"));
|
||||
assertTrue(root.hasIpAddress("192.168.1.224/27"));
|
||||
assertTrue(root.hasIpAddress("192.168.1.240/27"));
|
||||
assertTrue(root.hasIpAddress("192.168.1.255/32"));
|
||||
|
||||
request.setRemoteAddr("202.24.199.127");
|
||||
assertTrue(root.hasIpAddress("202.24.0.0/14"));
|
||||
request.setRemoteAddr("202.25.179.135");
|
||||
assertTrue(root.hasIpAddress("202.24.0.0/14"));
|
||||
request.setRemoteAddr("202.26.179.135");
|
||||
assertTrue(root.hasIpAddress("202.24.0.0/14"));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user