package org.jboss.web.tomcat.security;
import java.security.Principal;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Set;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.security.auth.Subject;
import EDU.oswego.cs.dl.util.concurrent.ConcurrentReaderHashMap;
import org.apache.catalina.LifecycleException;
import org.apache.catalina.Realm;
import org.apache.catalina.realm.RealmBase;
import org.jboss.logging.Logger;
import org.jboss.security.CertificatePrincipal;
import org.jboss.security.RealmMapping;
import org.jboss.security.SimplePrincipal;
import org.jboss.security.SubjectSecurityManager;
import org.jboss.security.auth.certs.SubjectDNMapping;
public class JBossSecurityMgrRealm extends RealmBase implements Realm
{
static Logger log = Logger.getLogger(JBossSecurityMgrRealm.class);
private CertificatePrincipal certMapping = new SubjectDNMapping();
private ConcurrentReaderHashMap roleMap = new ConcurrentReaderHashMap();
private boolean trace;
public void setCertificatePrincipal(String className)
{
try
{
ClassLoader loader = Thread.currentThread().getContextClassLoader();
Class cpClass = loader.loadClass(className);
certMapping = (CertificatePrincipal) cpClass.newInstance();
}
catch (Exception e)
{
log.error("Failed to load CertificatePrincipal: " + className, e);
certMapping = new SubjectDNMapping();
}
}
private Context getSecurityContext()
{
Context securityCtx = null;
try
{
InitialContext iniCtx = new InitialContext();
securityCtx = (Context) iniCtx.lookup("java:comp/env/security");
}
catch (NamingException e)
{
}
return securityCtx;
}
public void start() throws LifecycleException
{
if (super.started == true)
return;
super.start();
trace = log.isTraceEnabled();
}
public void stop() throws LifecycleException
{
if (super.started == false)
return;
super.stop();
}
public Principal authenticate(X509Certificate[] certs)
{
Principal principal = null;
Context securityCtx = getSecurityContext();
if (securityCtx == null)
{
if (trace)
log.trace("No security context for authenticate(X509Certificate[])");
return null;
}
try
{
SubjectSecurityManager securityMgr = (SubjectSecurityManager) securityCtx.lookup("securityMgr");
Subject subject = new Subject();
principal = certMapping.toPrinicipal(certs);
if (securityMgr.isValid(principal, certs, subject))
{
if (trace)
log.trace("User: " + principal + " is authenticated");
SecurityAssociationActions.setPrincipalInfo(principal, certs, subject);
RealmMapping realmMapping = (RealmMapping) securityCtx.lookup("realmMapping");
Principal oldPrincipal = principal;
principal = realmMapping.getPrincipal(oldPrincipal);
if (trace)
{
log.trace("Mapped from input principal: " + oldPrincipal
+ "to: " + principal);
}
principal = getCachingPrincpal(realmMapping, oldPrincipal,
principal, certs, subject);
}
else
{
if (trace)
log.trace("User: " + principal + " is NOT authenticated");
principal = null;
}
}
catch (NamingException e)
{
log.error("Error during authenticate", e);
}
return principal;
}
public Principal authenticate(String username, String digest, String nonce,
String nc, String cnonce, String qop, String realm, String md5a2)
{
return super.authenticate(username, digest, nonce,
nc, cnonce, qop, realm, md5a2);
}
public Principal authenticate(String username, String credentials)
{
if (trace)
log.trace("Begin authenticate, username=" + username);
Principal principal = null;
Context securityCtx = getSecurityContext();
if (securityCtx == null)
{
if (trace)
log.trace("No security context for authenticate(String, String)");
return null;
}
Principal caller = (Principal) SecurityAssociationValve.userPrincipal.get();
if (caller == null && username == null && credentials == null)
return null;
try
{
SubjectSecurityManager securityMgr = (SubjectSecurityManager) securityCtx.lookup("securityMgr");
principal = new SimplePrincipal(username);
Subject subject = new Subject();
if (securityMgr.isValid(principal, credentials, subject))
{
log.trace("User: " + username + " is authenticated");
SecurityAssociationActions.setPrincipalInfo(principal, credentials, subject);
RealmMapping realmMapping = (RealmMapping) securityCtx.lookup("realmMapping");
Principal oldPrincipal = principal;
principal = realmMapping.getPrincipal(oldPrincipal);
if (trace)
{
log.trace("Mapped from input principal: " + oldPrincipal
+ "to: " + principal);
}
principal = getCachingPrincpal(realmMapping, oldPrincipal,
principal, credentials, subject);
}
else
{
principal = null;
if (trace)
log.trace("User: " + username + " is NOT authenticated");
}
}
catch (NamingException e)
{
principal = null;
log.error("Error during authenticate", e);
}
if (trace)
log.trace("End authenticate, principal=" + principal);
return principal;
}
public boolean hasRole(Principal principal, String role)
{
if ((principal == null) || (role == null))
{
return false;
}
if (principal instanceof JBossGenericPrincipal)
{
return super.hasRole(principal, role);
}
JBossGenericPrincipal gp = (JBossGenericPrincipal) roleMap.get(principal);
Set userRoles = gp.getUserRoles();
if( userRoles != null )
{
Iterator iter = userRoles.iterator();
while( iter.hasNext() )
{
Principal p = (Principal) iter.next();
if (role.equals(p.getName()))
{
return true;
}
}
}
return false;
}
public Principal authenticate(String username, byte[] credentials)
{
return authenticate(username, new String(credentials));
}
protected String getName()
{
return getClass().getName();
}
protected String getPassword(String username)
{
String password = null;
return password;
}
protected Principal getPrincipal(String username)
{
return new SimplePrincipal(username);
}
protected Set getPrincipalRoles(Principal principal)
{
JBossGenericPrincipal gp = (JBossGenericPrincipal) roleMap.get(principal);
Set userRoles = gp.getUserRoles();
return userRoles;
}
protected Principal getCachingPrincpal(RealmMapping realmMapping,
Principal authPrincipal, Principal callerPrincipal, Object credential,
Subject subject)
{
Set userRoles = realmMapping.getUserRoles(authPrincipal);
ArrayList roles = new ArrayList();
if (userRoles != null)
{
Iterator iterator = userRoles.iterator();
while (iterator.hasNext())
{
Principal role = (Principal) iterator.next();
roles.add(role.getName());
}
}
JBossGenericPrincipal gp = new JBossGenericPrincipal(this, subject,
authPrincipal, callerPrincipal, credential, roles, userRoles);
roleMap.put(callerPrincipal, gp);
return gp;
}
}