/*
* Copyright (C) 2014 Intel Corporation
* All rights reserved.
*/
package com.intel.mtwilson.shiro.authz;
import java.util.HashSet;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import org.apache.shiro.web.filter.authz.AuthorizationFilter;
import com.intel.dcsg.cpg.net.InternetAddress;
import java.io.IOException;
import javax.servlet.http.HttpServletResponse;
import org.apache.shiro.util.StringUtils;
import org.apache.shiro.web.util.WebUtils;
/**
*
* @author jbuhacoff
*/
public class HostFilter extends AuthorizationFilter {
private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(HostFilter.class);
private HashSet<String> allowIp4 = new HashSet<>();
private HashSet<String> allowHost = new HashSet<>();
private String allowInput = null;
/**
*
* @param allow comma-separated list of hostnames or ip addresses; subnets
* and wildcards not yet supported
*/
public void setAllow(String allow) {
this.allowInput = allow;
String[] list = allow.replace(" ", "").split(",");
for (String item : list) {
log.debug("Allow from {}", item);
InternetAddress address = new InternetAddress(item);
if (address.isHostname()) {
allowHost.add(address.toString());
} else if (address.isIPv4()) {
allowIp4.add(address.toString());
} else {
log.error("Invalid address '{}'", item);
throw new IllegalArgumentException("Address must be hostname or IPv4");
}
}
}
public String getAllow() {
return allowInput;
}
@Override
protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) throws Exception {
log.debug("Remote addr = {}", request.getRemoteAddr());
log.debug("Remote host = {}", request.getRemoteHost());
InternetAddress remoteAddr = new InternetAddress(request.getRemoteAddr());
if (remoteAddr.isIPv4() && allowIp4.contains(remoteAddr.toString())) {
return true;
}
if (remoteAddr.isHostname() && allowHost.contains(remoteAddr.toString())) {
return true;
}
InternetAddress remoteHost = new InternetAddress(request.getRemoteHost());
if (remoteHost.isIPv4() && allowIp4.contains(remoteHost.toString())) {
return true;
}
if (remoteHost.isHostname() && allowHost.contains(remoteHost.toString())) {
return true;
}
return false;
}
/**
* Because a client accessing the service from a denied address has no
* possibility of logging in, the onAccessDenied behavior is modified to
* either return an error or redirect to the unauthorizedUrl (which would
* need to have the anon filter set to allow anyone to access it)
*
* @param request
* @param response
* @return
* @throws Exception
*/
@Override
protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws IOException {
if (StringUtils.hasText(getUnauthorizedUrl())) {
WebUtils.issueRedirect(request, response, getUnauthorizedUrl());
} else {
log.info("Access denied to unauthorized client {}", request.getRemoteAddr());
WebUtils.toHttp(response).sendError(HttpServletResponse.SC_UNAUTHORIZED);
}
return false;
}
}