package org.jboss.web.tomcat.security;
import java.io.IOException;
import java.security.Principal;
import java.security.Permission;
import java.security.ProtectionDomain;
import java.security.Policy;
import java.security.CodeSource;
import java.util.Set;
import javax.security.jacc.WebUserDataPermission;
import javax.security.jacc.PolicyContext;
import javax.security.jacc.WebResourcePermission;
import javax.security.jacc.WebRoleRefPermission;
import javax.security.jacc.PolicyContextException;
import javax.security.auth.Subject;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.catalina.Context;
import org.apache.catalina.Wrapper;
import org.apache.catalina.connector.Request;
import org.apache.catalina.connector.Response;
import org.apache.catalina.deploy.SecurityConstraint;
import org.jboss.logging.Logger;
public class JaccAuthorizationRealm extends JBossSecurityMgrRealm
{
static Logger log = Logger.getLogger(JaccAuthorizationRealm.class);
private static final String SUBJECT_CONTEXT_KEY = "javax.security.auth.Subject.container";
private static ThreadLocal activeRequest = new ThreadLocal();
private boolean trace;
private Policy policy;
public JaccAuthorizationRealm()
{
policy = Policy.getPolicy();
trace = log.isTraceEnabled();
}
public boolean hasResourcePermission(Request request, Response response,
SecurityConstraint[] securityConstraints, Context context)
throws IOException
{
Wrapper servlet = request.getWrapper();
if (servlet != null)
{
activeRequest.set(servlet.getName());
}
HttpServletRequest httpRequest = (HttpServletRequest) request.getRequest();
WebResourcePermission perm = new WebResourcePermission(httpRequest);
boolean allowed = checkSecurityAssociation(perm, request.getUserPrincipal());
if( trace )
log.trace("hasResourcePermission, perm="+perm+", allowed="+allowed);
if( allowed == false )
{
response.sendError(HttpServletResponse.SC_FORBIDDEN,
sm.getString("realmBase.forbidden"));
}
return allowed;
}
public boolean hasRole(Principal principal, String name)
{
String servletName = (String) activeRequest.get();
WebRoleRefPermission perm = new WebRoleRefPermission(servletName, name);
Principal[] principals = {principal};
Set roles = getPrincipalRoles(principal);
if( roles != null )
{
principals = new Principal[roles.size()];
roles.toArray(principals);
}
boolean allowed = checkSecurityAssociation(perm, principals);
if( trace )
log.trace("hasRole, perm="+perm+", allowed="+allowed);
return allowed;
}
public boolean hasUserDataPermission(Request request, Response response,
SecurityConstraint[] constraints) throws IOException
{
HttpServletRequest httpRequest = (HttpServletRequest) request.getRequest();
Principal requestPrincpal = httpRequest.getUserPrincipal();
establishSubjectContext(requestPrincpal);
WebUserDataPermission perm = new WebUserDataPermission(httpRequest);
if( trace )
log.trace("hasUserDataPermission, p="+perm);
boolean ok = false;
try
{
Principal[] principals = null;
ok = checkSecurityAssociation(perm, principals);
}
catch(Exception e)
{
if( trace )
log.trace("Failed to checkSecurityAssociation", e);
}
if( ok == false )
ok = super.hasUserDataPermission(request, response, constraints);
return ok;
}
private boolean checkSecurityAssociation(Permission perm, Principal requestPrincpal)
{
Subject caller = establishSubjectContext(requestPrincpal);
Principal[] principals = null;
if( caller != null )
{
if( trace )
log.trace("No active subject found, using ");
Set principalsSet = caller.getPrincipals();
principals = new Principal[principalsSet.size()];
principalsSet.toArray(principals);
}
return checkSecurityAssociation(perm, principals);
}
private boolean checkSecurityAssociation(Permission perm, Principal[] principals)
{
CodeSource webCS = (CodeSource) JaccContextValve.activeCS.get();
ProtectionDomain pd = new ProtectionDomain(webCS, null, null, principals);
boolean allowed = policy.implies(pd, perm);
if( trace )
{
String msg = (allowed ? "Allowed: " : "Denied: ") +perm;
log.trace(msg);
}
return allowed;
}
private Subject establishSubjectContext(Principal principal)
{
Subject caller = null;
try
{
caller = (Subject) PolicyContext.getContext(SUBJECT_CONTEXT_KEY);
}
catch (PolicyContextException e)
{
if( trace )
log.trace("Failed to get subject from PolicyContext", e);
}
if( caller == null )
{
if( principal instanceof JBossGenericPrincipal )
{
JBossGenericPrincipal jgp = (JBossGenericPrincipal) principal;
caller = jgp.getSubject();
if (trace)
log.trace("Restoring principal info from cache");
SecurityAssociationActions.setPrincipalInfo(jgp.getAuthPrincipal(),
jgp.getCredentials(), jgp.getSubject());
}
}
return caller;
}
}