/* The contents of this file are subject to the license and copyright terms
* detailed in the license directory at the root of the source tree (also
* available online at http://fedora-commons.org/license/).
*/
package fedora.server.security.servletfilters;
import java.util.Collection;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Vector;
import javax.servlet.FilterConfig;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* @author Bill Niebel
*/
public abstract class BaseContributing
extends FilterSetup {
protected static Log log = LogFactory.getLog(BaseContributing.class);
public static final HashSet NULL_SET = new HashSet();
public static final Hashtable EMPTY_MAP = new Hashtable();
public static final String[] EMPTY_ARRAY = new String[] {};
//defaults
private static boolean AUTHENTICATE_DEFAULT = true;
private static Collection FILTERS_CONTRIBUTING_SPONSORED_ATTRIBUTES_DEFAULT =
NULL_SET;
protected boolean AUTHENTICATE = AUTHENTICATE_DEFAULT;
protected Collection FILTERS_CONTRIBUTING_AUTHENTICATED_ATTRIBUTES =
NULL_SET;
protected Collection FILTERS_CONTRIBUTING_SPONSORED_ATTRIBUTES =
FILTERS_CONTRIBUTING_SPONSORED_ATTRIBUTES_DEFAULT;
public static final String SURROGATE_ROLE_KEY = "surrogate-role";
private static String SURROGATE_ROLE_DEFAULT = null;
protected String SURROGATE_ROLE = SURROGATE_ROLE_DEFAULT;
public static final String SURROGATE_ATTRIBUTE_KEY = "surrogate-attribute";
private static String SURROGATE_ATTRIBUTE_DEFAULT = null;
protected String SURROGATE_ATTRIBUTE = SURROGATE_ATTRIBUTE_DEFAULT;
public static final String USE_FILTER = "use-filter";
public static final String SKIP_FILTER = "skip-filter";
public static final String UNAUTHENTICATE_USER_UNCONDITIONALLY =
"unauthenticate-user-unconditionally";
public static final String UNAUTHENTICATE_USER_CONDITIONALLY =
"unauthenticate-user-conditionally";
public static final String PW_NULL_KEY = "null-password";
private static String PW_NULL_DEFAULT = USE_FILTER;
public String PW_NULL = PW_NULL_DEFAULT;
public static final String PW_0_KEY = "zerolength-password";
private static String PW_0_DEFAULT = USE_FILTER;
public String PW_0 = PW_0_DEFAULT;
public static final String EMPTY_RESULTS_KEY = "empty-results";
private static String EMPTY_RESULTS_DEFAULT =
UNAUTHENTICATE_USER_CONDITIONALLY;
public String EMPTY_RESULTS = EMPTY_RESULTS_DEFAULT;
public static final String LOG_STACK_TRACES_KEY = "log-stack-traces";
private static boolean LOG_STACK_TRACES_DEFAULT = false;
protected boolean LOG_STACK_TRACES = LOG_STACK_TRACES_DEFAULT;
@Override
public void init(FilterConfig filterConfig) {
String method = "init() ";
if (log.isDebugEnabled()) {
log.debug(enter(method));
}
super.init(filterConfig);
inited = false;
if (!initErrors) {
if (FILTERS_CONTRIBUTING_AUTHENTICATED_ATTRIBUTES.isEmpty()) {
if (FILTER_NAME == null || "".equals(FILTER_NAME)) {
initErrors = true;
if (log.isErrorEnabled()) {
log.error(format(method, "FILTER_NAME not set"));
}
} else {
FILTERS_CONTRIBUTING_AUTHENTICATED_ATTRIBUTES =
new Vector(1);
FILTERS_CONTRIBUTING_AUTHENTICATED_ATTRIBUTES
.add(FILTER_NAME);
}
}
}
if (initErrors) {
if (log.isErrorEnabled()) {
log
.error(format(method,
"FILTERS_CONTRIBUTING_AUTHENTICATED_ATTRIBUTES not set; see previous error"));
}
}
inited = true;
if (log.isDebugEnabled()) {
log.debug(exit(method));
}
}
@Override
public void destroy() {
String method = "destroy()";
if (log.isDebugEnabled()) {
log.debug(enter(method));
}
super.destroy();
if (log.isDebugEnabled()) {
log.debug(exit(method));
}
}
@Override
protected void initThisSubclass(String key, String value) {
String m = "initThisSubclass() ";
log.debug(m + ">");
if (SURROGATE_ROLE_KEY.equals(key)) {
SURROGATE_ROLE = value;
log.info(m + key + "==" + SURROGATE_ROLE);
} else if (SURROGATE_ATTRIBUTE_KEY.equals(key)) {
SURROGATE_ATTRIBUTE = value;
log.info(m + key + "==" + SURROGATE_ATTRIBUTE);
} else if (LOG_STACK_TRACES_KEY.equals(key)) {
try {
LOG_STACK_TRACES = Base.booleanValue(value);
log.info(m + key + "==" + LOG_STACK_TRACES);
} catch (Throwable t) {
initErrors = true;
log.error(m + "bad config " + key + "==" + value);
}
} else if (PW_NULL_KEY.equals(key)) {
if (SKIP_FILTER.equalsIgnoreCase(value)
|| USE_FILTER.equalsIgnoreCase(value)
|| UNAUTHENTICATE_USER_UNCONDITIONALLY
.equalsIgnoreCase(value)) {
PW_NULL = value;
log.info(m + key + "==" + PW_NULL);
} else {
initErrors = true;
log.error(m + "bad config " + key + "==" + value);
}
} else if (PW_0_KEY.equals(key)) {
if (SKIP_FILTER.equalsIgnoreCase(value)
|| USE_FILTER.equalsIgnoreCase(value)
|| UNAUTHENTICATE_USER_UNCONDITIONALLY
.equalsIgnoreCase(value)) {
PW_0 = value;
log.info(m + key + "==" + PW_0);
} else {
initErrors = true;
log.error(m + "bad config " + key + "==" + value);
}
} else if (EMPTY_RESULTS_KEY.equals(key)) {
if (SKIP_FILTER.equalsIgnoreCase(value)
|| USE_FILTER.equalsIgnoreCase(value)
|| UNAUTHENTICATE_USER_UNCONDITIONALLY
.equalsIgnoreCase(value)
|| UNAUTHENTICATE_USER_CONDITIONALLY
.equalsIgnoreCase(value)) {
EMPTY_RESULTS = value;
log.info(m + key + "==" + EMPTY_RESULTS);
} else {
initErrors = true;
log.error(m + "bad config " + key + "==" + value);
}
} else {
log.debug(m + "deferring " + key + " to super");
super.initThisSubclass(key, value);
}
log.debug(m + "<");
}
@Override
public boolean doThisSubclass(ExtendedHttpServletRequest extendedHttpServletRequest,
HttpServletResponse response)
throws Throwable {
String method = "doThisSubclass() ";
if (log.isDebugEnabled()) {
log.debug(enter(method));
}
super.doThisSubclass(extendedHttpServletRequest, response);
boolean alreadyAuthenticated =
extendedHttpServletRequest.getUserPrincipal() != null;
if (log.isDebugEnabled()) {
log.debug(format(method, null, "alreadyAuthenticated")
+ alreadyAuthenticated);
log.debug(format(method, null, "AUTHENTICATE") + AUTHENTICATE);
}
if (authenticate(alreadyAuthenticated)) {
if (log.isDebugEnabled()) {
log.debug(format(method, "calling authenticate() . . ."));
}
authenticate(extendedHttpServletRequest); //"authenticate" is really a conditional cache refresh . . . refactor name?
} else {
if (log.isDebugEnabled()) {
log.debug(format(method, "not calling authenticate()"));
}
}
String authority = extendedHttpServletRequest.getAuthority();
log.debug(format(method, null, "authority", authority));
if (authority != null && !"".equals(authority)) {
if (extendedHttpServletRequest.isUserSponsored()) {
log.debug(format(method, "user already sponsored")); //so neither get normal user attribute nor check for sponsored user
} else {
log.debug(format(method, "user not already sponsored"));
if (!FILTERS_CONTRIBUTING_AUTHENTICATED_ATTRIBUTES
.contains(authority)) {
if (log.isDebugEnabled()) {
log
.debug(format(method,
"not calling gatherAuthenticatedAttributes()"));
}
} else {
if (log.isDebugEnabled()) {
log
.debug(format(method,
"calling gatherAuthenticatedAttributes() . . ."));
}
contributeAuthenticatedAttributes(extendedHttpServletRequest);
//these newly-collect attributes could allow surrogate feature, so check:
boolean surrogateTurnedOnHere = false;
if (SURROGATE_ROLE == null || "".equals(SURROGATE_ROLE)) {
log
.debug(format(method,
"no surrogate role configured"));
} else {
log.debug(format(method,
"surrogate role configured",
SURROGATE_ROLE_KEY,
SURROGATE_ROLE));
if (extendedHttpServletRequest
.isUserInRole(SURROGATE_ROLE)) {
log
.debug(format(method,
"authenticated user has surrogate role"));
surrogateTurnedOnHere = true;
} else {
log
.debug(format(method,
"authenticated user doesn't have surrogate role"));
}
}
if (SURROGATE_ATTRIBUTE == null
|| "".equals(SURROGATE_ATTRIBUTE)) {
log.debug(format(method,
"no surrogate attribute configured"));
} else {
log.debug(format(method,
"surrogate attribute configured",
SURROGATE_ATTRIBUTE_KEY,
SURROGATE_ATTRIBUTE));
if (extendedHttpServletRequest
.isAttributeDefined(SURROGATE_ATTRIBUTE)) {
log
.debug(format(method,
"authenticated user has surrogate attribute"));
surrogateTurnedOnHere = true;
} else {
log
.debug(format(method,
"authenticated user doesn't have surrogate attribute"));
}
}
if (surrogateTurnedOnHere) {
log.debug(format(method, "setting user to sponsored"));
extendedHttpServletRequest.setSponsoredUser();
if (extendedHttpServletRequest.isUserSponsored()) {
log
.debug(format(method,
"verified that user is sponsored"));
} else {
log
.error(format(method,
"user is not correctly sponsored"));
}
}
}
}
if (extendedHttpServletRequest.isUserSponsored()) { //either from earlier filter or in this filter's code directly above
if (!FILTERS_CONTRIBUTING_SPONSORED_ATTRIBUTES
.contains(authority)) {
if (log.isDebugEnabled()) {
log
.debug(format(method,
"not calling gatherSponsoredAttributes()"));
}
} else {
if (log.isDebugEnabled()) {
log
.debug(format(method,
"calling gatherSponsoredAttributes() . . ."));
}
contributeSponsoredAttributes(extendedHttpServletRequest);
}
}
}
return false; // i.e., don't signal to terminate servlet filter chain
}
// NO CACHING AT THIS SUBCLASSING
abstract protected void authenticate(ExtendedHttpServletRequest extendedHttpServletRequest)
throws Exception;
abstract protected void contributeAuthenticatedAttributes(ExtendedHttpServletRequest extendedHttpServletRequest)
throws Exception;
abstract protected void contributeSponsoredAttributes(ExtendedHttpServletRequest extendedHttpServletRequest)
throws Exception;
abstract protected boolean authenticate(boolean alreadyAuthenticated);
}