I've been trying to dig through the JBoss source to understand how the caller
principal is set for the home.create() call, and I think it's possible that
there is a bug in the JBoss code. It's definitely possiblet hat Im wrong and I
am just not understanding something correctly, but let me show you what I
looked at.
In org.jboss.ejb.plugins.SecurityInterceptor#setContainer, if the
runAsCallerIdentity() == true, which is default, the runAsIdentity is never
initialized and remains null.
|public void setContainer(Container container)
|{
| super.setContainer(container);
| if (container != null)
| {
| BeanMetaData beanMetaData = container.getBeanMetaData();
| ApplicationMetaData applicationMetaData =
beanMetaData.getApplicationMetaData();
| AssemblyDescriptorMetaData assemblyDescriptor =
applicationMetaData.getAssemblyDescriptor();
| securityRoles = assemblyDescriptor.getSecurityRoles();
|
| SecurityIdentityMetaData secMetaData =
beanMetaData.getSecurityIdentityMetaData();
| if (secMetaData != null secMetaData.getUseCallerIdentity()
== false)
| {
| String roleName = secMetaData.getRunAsRoleName();
| String principalName = secMetaData.getRunAsPrincipalName();
|
| // the run-as principal might have extra roles mapped in
the assembly-descriptor
| Set extraRoleNames =
assemblyDescriptor.getSecurityRoleNamesByPrincipal(principalName);
| runAsIdentity = new RunAsIdentity(roleName, principalName,
extraRoleNames);
| }
|
| securityManager = container.getSecurityManager();
| realmMapping = container.getRealmMapping();
|
| try
| {
| // Get the timeout method
| ejbTimeout = TimedObject.class.getMethod(ejbTimeout, new
Class[]{Timer.class});
| }
| catch (NoSuchMethodException ignore)
| {
| }
| }
|}
Later on, in when an EJB looks up another EJB, the
org.jboss.ejb.plugins.SecurityInterceptor#invokeHome is called. There is a
call that indiscrimintately pushes the runAsIdentity onto the stack. Since
this is null from before, the next call is run with a null caller identity.
This is confirmed by the TRACE below.
|public Object invokeHome(Invocation mi) throws Exception
|{
| // Authenticate the subject and apply any declarative security checks
| checkSecurityAssociation(mi);
|
| /* If a run-as role was specified, push it so that any calls made
|by this bean will have the runAsRole available for declarative
|security checks.
| */
| SecurityActions.pushRunAsIdentity(runAsIdentity);
|
| try
| {
| Object returnValue = getNext().invokeHome(mi);
| return returnValue;
| }
| finally
| {
| SecurityActions.popRunAsIdentity();
| SecurityActions.popSubjectContext();
| }
|}
|
Here is the trace where you can see the caller identity of null being pushed,
and the subsequent exception that is caused by it.
| 2005-11-20 08:14:53,140 TRACE
[org.jboss.security.plugins.JaasSecurityManager.mwo] doesUserHaveRole(Set),
subject: Subject:
| Principal: admin
| Principal: Roles(members:Guest,Administrator)
|
| 2005-11-20 08:14:53,140 TRACE
[org.jboss.security.plugins.JaasSecurityManager.mwo]
roles=Roles(members:Guest,Administrator)
| 2005-11-20 08:14:53,140 TRACE
[org.jboss.security.plugins.JaasSecurityManager.mwo] hasRole(Administrator)=true
| 2005-11-20 08:14:53,140 TRACE
[org.jboss.security.plugins.JaasSecurityManager.mwo] hasRole=true
| 2005-11-20 08:14:53,140 TRACE [org.jboss.security.SecurityAssociation]
pushRunAsIdentity, runAs=null
| 2005-11-20 08:14:53,140 DEBUG [com.myejb.jboss.Session2SecurityProxy]
Entered setEJBContext(EJBContext)
| 2005-11-20 08:14:53,156 TRACE
[org.jboss.security.plugins.JaasSecurityManager.mwo] getPrincipal, cache info:
null
| 2005-11-20 08:14:53,156 TRACE [org.jboss.security.SecurityAssociation]
popRunAsIdentity, runAs=null
| 2005-11-20 08:14:53,156 TRACE [org.jboss.security.SecurityAssociation]
popSubjectContext, [EMAIL PROTECTED],subject=7683106}
| 2005-11-20 08:14:53,156 ERROR [org.jboss.ejb.plugins.LogInterceptor]
TransactionRolledbackException in method: public abstract
com.myejb.Session1Remote com.myejb.Session1Home.create() throws
javax.ejb.CreateException,java.rmi.RemoteException, causedBy:
| java.lang.IllegalStateException: No valid security context for the caller
identity
|
It seems the StatelessSessionInstanceInterceptor is responsible for pushing the
caller identity into the