Changing to list based request validation configuration

This commit is contained in:
Martin Stockhammer 2017-04-25 20:46:04 +02:00
parent 99a075f25f
commit 1b13cbd019
4 changed files with 320 additions and 102 deletions

View File

@ -162,4 +162,11 @@ public interface UserConfigurationKeys
String POLICY_PASSWORD_RULE_NOWHITTESPACE_ENABLED = "security.policy.password.rule.nowhitespace.enabled"; String POLICY_PASSWORD_RULE_NOWHITTESPACE_ENABLED = "security.policy.password.rule.nowhitespace.enabled";
String REST_BASE_URL = "rest.baseUrl";
String REST_CSRF_ABSENTORIGIN_DENY = "rest.csrffilter.absentorigin.deny";
String REST_CSRF_ENABLED = "rest.csrffilter.enabled";
String REST_CSRF_DISABLE_TOKEN_VALIDATION = "rest.csrffilter.disableTokenValidation";
} }

View File

@ -26,6 +26,7 @@ import org.apache.archiva.redback.authentication.TokenData;
import org.apache.archiva.redback.authentication.TokenManager; import org.apache.archiva.redback.authentication.TokenManager;
import org.apache.archiva.redback.authorization.RedbackAuthorization; import org.apache.archiva.redback.authorization.RedbackAuthorization;
import org.apache.archiva.redback.configuration.UserConfiguration; import org.apache.archiva.redback.configuration.UserConfiguration;
import org.apache.archiva.redback.configuration.UserConfigurationKeys;
import org.apache.archiva.redback.integration.filter.authentication.basic.HttpBasicAuthentication; import org.apache.archiva.redback.integration.filter.authentication.basic.HttpBasicAuthentication;
import org.apache.archiva.redback.policy.AccountLockedException; import org.apache.archiva.redback.policy.AccountLockedException;
import org.apache.archiva.redback.policy.MustChangePasswordException; import org.apache.archiva.redback.policy.MustChangePasswordException;
@ -47,6 +48,8 @@ import javax.ws.rs.ext.Provider;
import java.io.IOException; import java.io.IOException;
import java.net.MalformedURLException; import java.net.MalformedURLException;
import java.net.URL; import java.net.URL;
import java.util.ArrayList;
import java.util.List;
/** /**
* Created by Martin Stockhammer on 19.01.17. * Created by Martin Stockhammer on 19.01.17.
@ -73,10 +76,8 @@ public class RequestValidationInterceptor extends AbstractInterceptor implements
private static final String X_XSRF_TOKEN = "X-XSRF-TOKEN"; private static final String X_XSRF_TOKEN = "X-XSRF-TOKEN";
private static final String ORIGIN = "Origin"; private static final String ORIGIN = "Origin";
private static final String REFERER = "Referer"; private static final String REFERER = "Referer";
public static final String CFG_REST_BASE_URL = "rest.baseUrl"; private static final int DEFAULT_HTTP = 80;
public static final String CFG_REST_CSRF_ABSENTORIGIN_DENY = "rest.csrffilter.absentorigin.deny"; private static final int DEFAULT_HTTPS = 443;
public static final String CFG_REST_CSRF_ENABLED = "rest.csrffilter.enabled";
public static final String CFG_REST_CSRF_DISABLE_TOKEN_VALIDATION = "rest.csrffilter.disableTokenValidation";
private final Logger log = LoggerFactory.getLogger( getClass() ); private final Logger log = LoggerFactory.getLogger( getClass() );
@ -84,11 +85,9 @@ public class RequestValidationInterceptor extends AbstractInterceptor implements
private boolean checkToken = true; private boolean checkToken = true;
private boolean useStaticUrl = false; private boolean useStaticUrl = false;
private boolean denyAbsentHeaders = true; private boolean denyAbsentHeaders = true;
private URL baseUrl; private List<URL> baseUrl = new ArrayList<URL>();
private HttpServletRequest httpRequest = null; private HttpServletRequest httpRequest = null;
private UserConfiguration config;
@Inject @Inject
@Named( value = "httpAuthenticator#basic" ) @Named( value = "httpAuthenticator#basic" )
private HttpBasicAuthentication httpAuthenticator; private HttpBasicAuthentication httpAuthenticator;
@ -97,31 +96,197 @@ public class RequestValidationInterceptor extends AbstractInterceptor implements
@Named( value = "tokenManager#default") @Named( value = "tokenManager#default")
TokenManager tokenManager; TokenManager tokenManager;
private UserConfiguration config;
private class HeaderValidationInfo {
final static int UNKNOWN = -1;
final static int OK = 0;
final static int F_REFERER_HOST = 1;
final static int F_REFERER_PORT = 2;
final static int F_ORIGIN_HOST = 8;
final static int F_ORIGIN_PORT = 16;
final static int F_ORIGIN_PROTOCOL = 32;
boolean headerFound = false;
URL targetUrl;
URL originUrl;
URL refererUrl;
String targetHost;
String originHost;
String refererHost;
int targetPort;
int originPort;
int refererPort;
int status = UNKNOWN;
public HeaderValidationInfo(URL targetUrl) {
setTargetUrl(targetUrl);
}
public URL getTargetUrl() {
return targetUrl;
}
public void setTargetUrl(URL targetUrl) {
this.targetUrl = targetUrl;
this.targetHost=getHost(targetUrl);
this.targetPort=getPort(targetUrl);
}
public URL getOriginUrl() {
return originUrl;
}
public void setOriginUrl(URL originUrl) {
this.originUrl=originUrl;
this.originHost=getHost(originUrl);
this.originPort=getPort(originUrl);
checkOrigin();
this.headerFound=true;
}
public URL getRefererUrl() {
return refererUrl;
}
public void setRefererUrl(URL refererUrl) {
this.refererUrl=refererUrl;
this.refererHost=getHost(refererUrl);
this.refererPort=getPort(refererUrl);
checkReferer();
this.headerFound=true;
}
public String getTargetHost() {
return targetHost;
}
public void setTargetHost(String targetHost) {
this.targetHost = targetHost;
}
public String getOriginHost() {
return originHost;
}
public void setOriginHost(String originHost) {
this.originHost = originHost;
}
public String getRefererHost() {
return refererHost;
}
public void setRefererHost(String refererHost) {
this.refererHost = refererHost;
}
public int getTargetPort() {
return targetPort;
}
public void setTargetPort(int targetPort) {
this.targetPort = targetPort;
}
public int getOriginPort() {
return originPort;
}
public void setOriginPort(int originPort) {
this.originPort = originPort;
}
public int getRefererPort() {
return refererPort;
}
public void setRefererPort(int refererPort) {
this.refererPort = refererPort;
}
public void setStatus(int status) {
this.status |= status;
}
public int getStatus() {
return this.status;
}
// Origin check for Protocol, Host, Port
public void checkOrigin() {
if (this.getStatus()==UNKNOWN) {
this.status=OK;
}
if (!targetUrl.getProtocol().equals(originUrl.getProtocol())) {
setStatus(F_ORIGIN_PROTOCOL);
}
if (!targetHost.equals(originHost)) {
setStatus(F_ORIGIN_HOST);
}
if (targetPort!=originPort) {
setStatus(F_ORIGIN_PORT);
}
}
// Referer check only for Host, Port
public void checkReferer() {
if (this.getStatus()==UNKNOWN) {
this.status=OK;
}
if (!targetHost.equals(refererHost)) {
setStatus(F_REFERER_HOST);
}
if (targetPort!=refererPort) {
setStatus(F_REFERER_PORT);
}
}
public boolean hasOriginError() {
return (status & (F_ORIGIN_PROTOCOL | F_ORIGIN_HOST | F_ORIGIN_PORT)) > 0;
}
public boolean hasRefererError() {
return (status & (F_REFERER_HOST | F_REFERER_PORT )) > 0;
}
@Override
public String toString() {
return "Stat="+status+", target="+targetUrl+", origin="+originUrl+", referer="+refererUrl;
}
}
@Inject @Inject
public RequestValidationInterceptor(@Named( value = "userConfiguration#default" ) public RequestValidationInterceptor(
UserConfiguration config) { @Named(value = "userConfiguration#default") UserConfiguration config) {
this.config = config; this.config = config;
} }
@PostConstruct @PostConstruct
public void init() { public void init() {
String baseUrlStr = config.getString(CFG_REST_BASE_URL, ""); List<String> baseUrlList = config.getList(UserConfigurationKeys.REST_BASE_URL);
if (!"".equals(baseUrlStr.trim())) { if (baseUrlList!=null) {
try { for (String baseUrlStr : baseUrlList) {
baseUrl = new URL(baseUrlStr); if (!"".equals(baseUrlStr.trim())) {
useStaticUrl = true; try {
} catch (MalformedURLException ex) { baseUrl.add(new URL(baseUrlStr));
log.error("Configured baseUrl (rest.baseUrl={}) is invalid. Message: {}", baseUrlStr, ex.getMessage()); useStaticUrl = true;
} catch (MalformedURLException ex) {
log.error("Configured baseUrl (rest.baseUrl={}) is invalid. Message: {}", baseUrlStr, ex.getMessage());
}
}
} }
} else {
useStaticUrl = false;
} }
denyAbsentHeaders = config.getBoolean(CFG_REST_CSRF_ABSENTORIGIN_DENY,true); denyAbsentHeaders = config.getBoolean(UserConfigurationKeys.REST_CSRF_ABSENTORIGIN_DENY,true);
enabled = config.getBoolean(CFG_REST_CSRF_ENABLED,true); enabled = config.getBoolean(UserConfigurationKeys.REST_CSRF_ENABLED,true);
if (!enabled) { if (!enabled) {
log.info("CSRF Filter is disabled by configuration"); log.info("CSRF Filter is disabled by configuration");
} }
checkToken = !config.getBoolean(CFG_REST_CSRF_DISABLE_TOKEN_VALIDATION, false); checkToken = !config.getBoolean(UserConfigurationKeys.REST_CSRF_DISABLE_TOKEN_VALIDATION, false);
if (!checkToken) { if (!checkToken) {
log.info("CSRF Token validation is disabled by configuration"); log.info("CSRF Token validation is disabled by configuration");
} }
@ -131,24 +296,62 @@ public class RequestValidationInterceptor extends AbstractInterceptor implements
public void filter(ContainerRequestContext containerRequestContext) throws IOException { public void filter(ContainerRequestContext containerRequestContext) throws IOException {
if (enabled) { if (enabled) {
HttpServletRequest request = getRequest(); HttpServletRequest request = getRequest();
URL targetUrl = getTargetUrl(request); List<URL> targetUrls = getTargetUrl(request);
if (targetUrl == null) { if (targetUrls == null) {
log.error("Could not verify target URL."); log.error("Could not verify target URL.");
containerRequestContext.abortWith(Response.status(Response.Status.FORBIDDEN).build()); containerRequestContext.abortWith(Response.status(Response.Status.FORBIDDEN).build());
return; return;
} }
if (!checkSourceRequestHeader(targetUrl, request)) { List<HeaderValidationInfo> validationInfos = new ArrayList<HeaderValidationInfo>();
log.warn("HTTP Header check failed. Assuming CSRF attack."); boolean targetMatch=false;
boolean noHeader = true;
for(URL targetUrl : targetUrls) {
log.trace("Checking against target URL: {}", targetUrl);
HeaderValidationInfo info = checkSourceRequestHeader(new HeaderValidationInfo(targetUrl), request);
// We need only one match
noHeader = noHeader && info.getStatus()==info.UNKNOWN;
if (info.getStatus()==info.OK) {
targetMatch=true;
break;
} else {
validationInfos.add(info);
}
}
if (noHeader && denyAbsentHeaders) {
log.warn("Request denied. No Origin or Referer header found and {}=true", UserConfigurationKeys.REST_CSRF_ABSENTORIGIN_DENY);
containerRequestContext.abortWith(Response.status(Response.Status.FORBIDDEN).build());
return;
}
if (!targetMatch) {
log.warn("HTTP Header check failed. Assuming CSRF attack.");
for(HeaderValidationInfo info : validationInfos) {
if (info.hasOriginError()) {
log.warn("Origin Header does not match: originUrl={}, targetUrl={}. Matches: Host={}, Port={}, Protocol={}",
info.originUrl, info.targetUrl, (info.getStatus()&info.F_ORIGIN_HOST)==0,
(info.getStatus()&info.F_ORIGIN_PORT)==0, (info.getStatus()&info.F_ORIGIN_PROTOCOL)==0);
}
if (info.hasRefererError()) {
log.warn("Referer Header does not match: refererUrl={}, targetUrl={}. Matches: Host={}, Port={}",
info.refererUrl, info.targetUrl, (info.getStatus()&info.F_REFERER_HOST)==0,
(info.getStatus()&info.F_REFERER_PORT)==0);
}
}
containerRequestContext.abortWith(Response.status(Response.Status.FORBIDDEN).build()); containerRequestContext.abortWith(Response.status(Response.Status.FORBIDDEN).build());
return; return;
} }
if (checkToken) { if (checkToken) {
checkValidationToken(containerRequestContext, request); checkValidationToken(containerRequestContext, request);
} }
} }
} }
/**
* Checks the request for a validation token header. It takes the encrypted token, decrypts it
* and compares the user information from the token to the logged in user.
*
* @param containerRequestContext
* @param request
*/
private void checkValidationToken(ContainerRequestContext containerRequestContext, HttpServletRequest request) { private void checkValidationToken(ContainerRequestContext containerRequestContext, HttpServletRequest request) {
Message message = JAXRSUtils.getCurrentMessage(); Message message = JAXRSUtils.getCurrentMessage();
RedbackAuthorization redbackAuthorization = getRedbackAuthorization(message); RedbackAuthorization redbackAuthorization = getRedbackAuthorization(message);
@ -198,13 +401,15 @@ public class RequestValidationInterceptor extends AbstractInterceptor implements
} }
} }
private URL getTargetUrl(HttpServletRequest request) { private List<URL> getTargetUrl(HttpServletRequest request) {
if (useStaticUrl) { if (useStaticUrl) {
return baseUrl; return baseUrl;
} else { } else {
List<URL> urls = new ArrayList<URL>();
URL requestUrl; URL requestUrl;
try { try {
requestUrl = new URL(request.getRequestURL().toString()); requestUrl = new URL(request.getRequestURL().toString());
urls.add(requestUrl);
} catch (MalformedURLException ex) { } catch (MalformedURLException ex) {
log.error("Bad Request URL {}, Message: {}", request.getRequestURL(), ex.getMessage()); log.error("Bad Request URL {}, Message: {}", request.getRequestURL(), ex.getMessage());
return null; return null;
@ -216,81 +421,52 @@ public class RequestValidationInterceptor extends AbstractInterceptor implements
} }
if (xforwarded!=null) { if (xforwarded!=null) {
try { try {
return new URL(xforwardedProto+"://"+xforwarded); urls.add(new URL(xforwardedProto+"://"+xforwarded));
} catch (MalformedURLException ex) { } catch (MalformedURLException ex) {
log.warn("X-Forwarded-Host Header is malformed: {}", ex.getMessage()); log.warn("X-Forwarded-Host Header is malformed: {}", ex.getMessage());
} }
} }
return requestUrl; return urls;
} }
} }
private int getPort(final URL url) { private int getPort(final URL url) {
return url.getPort() > 0 ? url.getPort() : url.getDefaultPort(); return url.getPort() > 0 ? url.getPort() : ("https".equals(url.getProtocol()) ? DEFAULT_HTTPS : DEFAULT_HTTP);
} }
private boolean checkSourceRequestHeader(final URL targetUrl, final HttpServletRequest request) { private String getHost(final URL url) {
boolean headerFound=false; return url.getHost().trim().toLowerCase();
}
/**
* Checks the validation headers. First the Origin header is checked, if this fails
* or is absent, the referer header is checked.
*
* @param info The info object that must be populated with the targetURL
* @param request The HTTP request object
* @return A info object with updated status information
*/
private HeaderValidationInfo checkSourceRequestHeader(final HeaderValidationInfo info, final HttpServletRequest request) {
String origin = request.getHeader(ORIGIN); String origin = request.getHeader(ORIGIN);
int targetPort = getPort(targetUrl);
if (origin!=null) { if (origin!=null) {
try { try {
URL originUrl = new URL(origin); info.setOriginUrl(new URL(origin));
headerFound=true; } catch (MalformedURLException e) {
log.debug("Origin Header URL found: {}", originUrl); log.warn("Bad origin header found: {}", origin);
if (!targetUrl.getProtocol().equals(originUrl.getProtocol())) {
log.warn("Origin Header Protocol does not match originUrl={}, targetUrl={}", //
originUrl.getProtocol(), //
targetUrl.getProtocol());
return false;
}
if (!targetUrl.getHost().equals(originUrl.getHost())) {
log.warn("Origin Header Host does not match originUrl='{}', targetUrl='{}'",
originUrl.getProtocol(), //
targetUrl.getProtocol());
return false;
}
int originPort = getPort(originUrl);
if (targetPort != originPort) {
log.warn("Origin Header Port does not match originUrl={}, targetUrl={}",
originUrl.getPort(),
targetUrl.getPort());
return false;
}
} catch (MalformedURLException ex) {
log.warn("Bad URL in Origin HTTP-Header: {}. Message: {}",origin, ex.getMessage());
return false;
} }
} }
String referer = request.getHeader(REFERER); // Check referer if Origin header dos not match or is not available
if (referer!=null) { if (info.getStatus()!=info.OK) {
try { String referer = request.getHeader(REFERER);
URL refererUrl = new URL(referer); if (referer != null) {
headerFound=true; try {
log.debug("Referer Header URL found: {}",refererUrl); info.setRefererUrl(new URL(referer));
if (!targetUrl.getHost().equals(refererUrl.getHost())) { } catch (MalformedURLException ex) {
log.warn("Referer Header Host does not match refererUrl='{}', targetUrl='{}'", // log.warn("Bad URL in Referer HTTP-Header: {}, Message: {}", referer, ex.getMessage());
refererUrl.getHost(), //
targetUrl.getHost());
return false;
} }
int refererPort = getPort(refererUrl);
if (targetPort != refererPort) {
log.warn("Referer Header Port does not match refererUrl={}, targetUrl={}", //
refererUrl.getPort(),
targetUrl.getPort());
return false;
}
} catch (MalformedURLException ex) {
log.warn("Bad URL in Referer HTTP-Header: {}, Message: {}", referer, ex.getMessage());
return false;
} }
} }
if (!headerFound && denyAbsentHeaders) { return info;
log.warn("Neither Origin nor Referer header found. Request is denied.");
return false;
}
return true;
} }
public void setHttpRequest(HttpServletRequest request) { public void setHttpRequest(HttpServletRequest request) {

View File

@ -22,17 +22,18 @@ package org.apache.archiva.redback.rest.services;
import junit.framework.TestCase; import junit.framework.TestCase;
import org.apache.archiva.redback.authentication.TokenManager; import org.apache.archiva.redback.authentication.TokenManager;
import org.apache.archiva.redback.configuration.UserConfigurationException; import org.apache.archiva.redback.configuration.UserConfigurationException;
import org.apache.archiva.redback.configuration.UserConfigurationKeys;
import org.apache.archiva.redback.rest.services.interceptors.RequestValidationInterceptor; import org.apache.archiva.redback.rest.services.interceptors.RequestValidationInterceptor;
import org.apache.archiva.redback.rest.services.mock.MockContainerRequestContext; import org.apache.archiva.redback.rest.services.mock.MockContainerRequestContext;
import org.apache.archiva.redback.rest.services.mock.MockUserConfiguration; import org.apache.archiva.redback.rest.services.mock.MockUserConfiguration;
import org.apache.archiva.redback.system.SecuritySystem;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.junit.runners.JUnit4; import org.junit.runners.JUnit4;
import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockHttpServletRequest;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
/** /**
@ -50,7 +51,7 @@ public class RequestValidationInterceptorTest extends TestCase {
public void validateRequestWithoutHeader() throws UserConfigurationException, IOException { public void validateRequestWithoutHeader() throws UserConfigurationException, IOException {
TokenManager tm = new TokenManager(); TokenManager tm = new TokenManager();
MockUserConfiguration cfg = new MockUserConfiguration(); MockUserConfiguration cfg = new MockUserConfiguration();
cfg.addValue(RequestValidationInterceptor.CFG_REST_CSRF_DISABLE_TOKEN_VALIDATION,"true"); cfg.addValue(UserConfigurationKeys.REST_CSRF_DISABLE_TOKEN_VALIDATION,"true");
RequestValidationInterceptor interceptor = new RequestValidationInterceptor(cfg); RequestValidationInterceptor interceptor = new RequestValidationInterceptor(cfg);
MockHttpServletRequest request = new MockHttpServletRequest(); MockHttpServletRequest request = new MockHttpServletRequest();
interceptor.setHttpRequest(request); interceptor.setHttpRequest(request);
@ -64,7 +65,7 @@ public class RequestValidationInterceptorTest extends TestCase {
public void validateRequestWithOrigin() throws UserConfigurationException, IOException { public void validateRequestWithOrigin() throws UserConfigurationException, IOException {
TokenManager tm = new TokenManager(); TokenManager tm = new TokenManager();
MockUserConfiguration cfg = new MockUserConfiguration(); MockUserConfiguration cfg = new MockUserConfiguration();
cfg.addValue(RequestValidationInterceptor.CFG_REST_CSRF_DISABLE_TOKEN_VALIDATION,"true"); cfg.addValue(UserConfigurationKeys.REST_CSRF_DISABLE_TOKEN_VALIDATION,"true");
RequestValidationInterceptor interceptor = new RequestValidationInterceptor(cfg); RequestValidationInterceptor interceptor = new RequestValidationInterceptor(cfg);
MockHttpServletRequest request = new MockHttpServletRequest("GET","/api/v1/userService"); MockHttpServletRequest request = new MockHttpServletRequest("GET","/api/v1/userService");
request.setServerName("test.archiva.org"); request.setServerName("test.archiva.org");
@ -80,7 +81,7 @@ public class RequestValidationInterceptorTest extends TestCase {
public void validateRequestWithBadOrigin() throws UserConfigurationException, IOException { public void validateRequestWithBadOrigin() throws UserConfigurationException, IOException {
TokenManager tm = new TokenManager(); TokenManager tm = new TokenManager();
MockUserConfiguration cfg = new MockUserConfiguration(); MockUserConfiguration cfg = new MockUserConfiguration();
cfg.addValue(RequestValidationInterceptor.CFG_REST_CSRF_DISABLE_TOKEN_VALIDATION,"true"); cfg.addValue(UserConfigurationKeys.REST_CSRF_DISABLE_TOKEN_VALIDATION,"true");
RequestValidationInterceptor interceptor = new RequestValidationInterceptor(cfg); RequestValidationInterceptor interceptor = new RequestValidationInterceptor(cfg);
MockHttpServletRequest request = new MockHttpServletRequest("GET","/api/v1/userService"); MockHttpServletRequest request = new MockHttpServletRequest("GET","/api/v1/userService");
request.setServerName("test.archiva.org"); request.setServerName("test.archiva.org");
@ -96,7 +97,7 @@ public class RequestValidationInterceptorTest extends TestCase {
public void validateRequestWithReferer() throws UserConfigurationException, IOException { public void validateRequestWithReferer() throws UserConfigurationException, IOException {
TokenManager tm = new TokenManager(); TokenManager tm = new TokenManager();
MockUserConfiguration cfg = new MockUserConfiguration(); MockUserConfiguration cfg = new MockUserConfiguration();
cfg.addValue(RequestValidationInterceptor.CFG_REST_CSRF_DISABLE_TOKEN_VALIDATION,"true"); cfg.addValue(UserConfigurationKeys.REST_CSRF_DISABLE_TOKEN_VALIDATION,"true");
RequestValidationInterceptor interceptor = new RequestValidationInterceptor(cfg); RequestValidationInterceptor interceptor = new RequestValidationInterceptor(cfg);
MockHttpServletRequest request = new MockHttpServletRequest("GET","/api/v1/userService"); MockHttpServletRequest request = new MockHttpServletRequest("GET","/api/v1/userService");
request.setServerName("test.archiva.org"); request.setServerName("test.archiva.org");
@ -112,7 +113,7 @@ public class RequestValidationInterceptorTest extends TestCase {
public void validateRequestWithBadReferer() throws UserConfigurationException, IOException { public void validateRequestWithBadReferer() throws UserConfigurationException, IOException {
TokenManager tm = new TokenManager(); TokenManager tm = new TokenManager();
MockUserConfiguration cfg = new MockUserConfiguration(); MockUserConfiguration cfg = new MockUserConfiguration();
cfg.addValue(RequestValidationInterceptor.CFG_REST_CSRF_DISABLE_TOKEN_VALIDATION,"true"); cfg.addValue(UserConfigurationKeys.REST_CSRF_DISABLE_TOKEN_VALIDATION,"true");
RequestValidationInterceptor interceptor = new RequestValidationInterceptor(cfg); RequestValidationInterceptor interceptor = new RequestValidationInterceptor(cfg);
MockHttpServletRequest request = new MockHttpServletRequest("GET","/api/v1/userService"); MockHttpServletRequest request = new MockHttpServletRequest("GET","/api/v1/userService");
request.setServerName("test.archiva.org"); request.setServerName("test.archiva.org");
@ -128,7 +129,7 @@ public class RequestValidationInterceptorTest extends TestCase {
public void validateRequestWithOriginAndReferer() throws UserConfigurationException, IOException { public void validateRequestWithOriginAndReferer() throws UserConfigurationException, IOException {
TokenManager tm = new TokenManager(); TokenManager tm = new TokenManager();
MockUserConfiguration cfg = new MockUserConfiguration(); MockUserConfiguration cfg = new MockUserConfiguration();
cfg.addValue(RequestValidationInterceptor.CFG_REST_CSRF_DISABLE_TOKEN_VALIDATION,"true"); cfg.addValue(UserConfigurationKeys.REST_CSRF_DISABLE_TOKEN_VALIDATION,"true");
RequestValidationInterceptor interceptor = new RequestValidationInterceptor(cfg); RequestValidationInterceptor interceptor = new RequestValidationInterceptor(cfg);
MockHttpServletRequest request = new MockHttpServletRequest("GET","/api/v1/userService"); MockHttpServletRequest request = new MockHttpServletRequest("GET","/api/v1/userService");
request.setServerName("test.archiva.org"); request.setServerName("test.archiva.org");
@ -145,8 +146,10 @@ public class RequestValidationInterceptorTest extends TestCase {
@Test @Test
public void validateRequestWithOriginAndStaticUrl() throws UserConfigurationException, IOException { public void validateRequestWithOriginAndStaticUrl() throws UserConfigurationException, IOException {
MockUserConfiguration cfg = new MockUserConfiguration(); MockUserConfiguration cfg = new MockUserConfiguration();
cfg.addValue("rest.baseUrl","http://test.archiva.org"); List<String> urls = new ArrayList<String>();
cfg.addValue(RequestValidationInterceptor.CFG_REST_CSRF_DISABLE_TOKEN_VALIDATION,"true"); urls.add("http://test.archiva.org");
cfg.addList("rest.baseUrl",urls);
cfg.addValue(UserConfigurationKeys.REST_CSRF_DISABLE_TOKEN_VALIDATION,"true");
TokenManager tm = new TokenManager(); TokenManager tm = new TokenManager();
RequestValidationInterceptor interceptor = new RequestValidationInterceptor(cfg); RequestValidationInterceptor interceptor = new RequestValidationInterceptor(cfg);
MockHttpServletRequest request = new MockHttpServletRequest("GET","/api/v1/userService"); MockHttpServletRequest request = new MockHttpServletRequest("GET","/api/v1/userService");
@ -162,8 +165,10 @@ public class RequestValidationInterceptorTest extends TestCase {
@Test @Test
public void validateRequestWithBadOriginAndStaticUrl() throws UserConfigurationException, IOException { public void validateRequestWithBadOriginAndStaticUrl() throws UserConfigurationException, IOException {
MockUserConfiguration cfg = new MockUserConfiguration(); MockUserConfiguration cfg = new MockUserConfiguration();
cfg.addValue("rest.baseUrl","http://mytest.archiva.org"); List<String> urls = new ArrayList<String>();
cfg.addValue(RequestValidationInterceptor.CFG_REST_CSRF_DISABLE_TOKEN_VALIDATION,"true"); urls.add("http://mytest.archiva.org");
cfg.addList("rest.baseUrl",urls);
cfg.addValue(UserConfigurationKeys.REST_CSRF_DISABLE_TOKEN_VALIDATION,"true");
TokenManager tm = new TokenManager(); TokenManager tm = new TokenManager();
RequestValidationInterceptor interceptor = new RequestValidationInterceptor(cfg); RequestValidationInterceptor interceptor = new RequestValidationInterceptor(cfg);
MockHttpServletRequest request = new MockHttpServletRequest("GET","/api/v1/userService"); MockHttpServletRequest request = new MockHttpServletRequest("GET","/api/v1/userService");
@ -177,4 +182,25 @@ public class RequestValidationInterceptorTest extends TestCase {
} }
@Test
public void validateRequestWithOriginListAndStaticUrl() throws UserConfigurationException, IOException {
MockUserConfiguration cfg = new MockUserConfiguration();
List<String> urls = new ArrayList<String>();
urls.add("http://mytest.archiva.org");
urls.add("http://mytest2.archiva.org");
urls.add("http://test.archiva.org");
cfg.addList("rest.baseUrl",urls);
cfg.addValue(UserConfigurationKeys.REST_CSRF_DISABLE_TOKEN_VALIDATION,"true");
TokenManager tm = new TokenManager();
RequestValidationInterceptor interceptor = new RequestValidationInterceptor(cfg);
MockHttpServletRequest request = new MockHttpServletRequest("GET","/api/v1/userService");
request.setServerName("mytest.archiva.org");
request.addHeader("Origin","http://test.archiva.org/myservlet");
interceptor.setHttpRequest(request);
interceptor.init();
MockContainerRequestContext ctx = new MockContainerRequestContext();
interceptor.filter(ctx);
assertFalse(ctx.isAborted());
}
} }

View File

@ -34,13 +34,17 @@ import java.util.Map;
*/ */
public class MockUserConfiguration implements UserConfiguration { public class MockUserConfiguration implements UserConfiguration {
private Map<String, String> values = new java.util.HashMap<String,String>(); private Map<String, Object> values = new java.util.HashMap<String,Object>();
@SuppressWarnings("SameParameterValue") @SuppressWarnings("SameParameterValue")
public void addValue(String key, String value) { public void addValue(String key, String value) {
values.put(key,value); values.put(key,value);
} }
public void addList(String key, List<String> listValue) {
values.put(key, listValue);
}
@Override @Override
public void initialize() throws UserConfigurationException { public void initialize() throws UserConfigurationException {
@ -48,13 +52,13 @@ public class MockUserConfiguration implements UserConfiguration {
@Override @Override
public String getString(String key) { public String getString(String key) {
return values.get(key); return values.get(key).toString();
} }
@Override @Override
public String getString(String key, String defaultValue) { public String getString(String key, String defaultValue) {
if (values.containsKey(key)) { if (values.containsKey(key)) {
return values.get(key); return values.get(key).toString();
} else { } else {
return defaultValue; return defaultValue;
} }
@ -68,7 +72,7 @@ public class MockUserConfiguration implements UserConfiguration {
@Override @Override
public int getInt(String key, int defaultValue) { public int getInt(String key, int defaultValue) {
if (values.containsKey(key)) { if (values.containsKey(key)) {
return Integer.parseInt(values.get(key)); return Integer.parseInt(values.get(key).toString());
} else { } else {
return defaultValue; return defaultValue;
} }
@ -82,7 +86,7 @@ public class MockUserConfiguration implements UserConfiguration {
@Override @Override
public boolean getBoolean(String key, boolean defaultValue) { public boolean getBoolean(String key, boolean defaultValue) {
if (values.containsKey(key)) { if (values.containsKey(key)) {
return Boolean.parseBoolean(values.get(key)); return Boolean.parseBoolean(values.get(key).toString());
} else { } else {
return defaultValue; return defaultValue;
} }
@ -90,7 +94,12 @@ public class MockUserConfiguration implements UserConfiguration {
@Override @Override
public List<String> getList(String key) { public List<String> getList(String key) {
return null; Object value = values.get(key);
if (value!=null && value instanceof List) {
return (List)value;
} else {
return null;
}
} }
@Override @Override