0 Replies Latest reply on Nov 1, 2011 4:57 AM by doychin

    Problem when invoking Local EJB from new thread

    doychin

      During my migration to JBoss AS 5/6 I found this problem and it lies within a new PreSecurity interceptor plus the change that SecurityContext is now shared between all threads.

       

      So I changed my startup configuration to include -Dorg.jboss.security.context.ThreadLocal=true

      and also made changes from https://issues.jboss.org/browse/JBAS-7037

       

      Here is the end result:

       

         private Object process(Invocation mi, boolean isInvoke) throws Exception

         {

            //No Security in the absence of SecurityDomain

            if(securityDomain == null)

            {

               if(isInvoke)

                  return getNext().invoke(mi);

               else

                  return getNext().invokeHome(mi);

            }

       

            if(log.isTraceEnabled()) {

                log.trace("process:isInvoke=" + isInvoke + " bean=" + container.getServiceName());

            }

            SecurityIdentity si = null;

            String incomingDomain  = null;

            Method m = mi.getMethod();

            boolean isEjbTimeOutMethod = m != null && m.getName().equals(timedObjectMethod);

            //For local ejb invocations

            if(mi.isLocal() && !isEjbTimeOutMethod) {

                if(log.isTraceEnabled()) {

                    log.trace("True mi.isLocal() && !isEjbTimeOutMethod");

                }

                //Cache the security context

                SecurityContext sc = SecurityActions.getSecurityContext();

                if(sc == null) {

                    if(log.isTraceEnabled()) {

                        log.trace("sc is null");

                        log.trace("creating security context for domain " + securityDomain);

                    }

                    sc = SecurityActions.createAndSetSecurityContext(securityDomain,

                        container.getSecurityContextClassName());

                } else {

                    incomingDomain = sc.getSecurityDomain();

                    if(log.isTraceEnabled()) {

                          log.trace("incoming domain is " + incomingDomain);

                        log.trace("sc id " + Integer.toHexString(sc.hashCode()));

                    }

                }

       

                si = SecurityActions.getSecurityIdentity(sc);

       

                SecurityActions.setSecurityManagement(sc, container.getSecurityManagement());

                // set the container's security domain in the security context

                SecurityActions.setSecurityDomain(sc, this.securityDomain);

                if(log.isTraceEnabled()) {

                      log.trace("setting security domain to " + securityDomain);

                      log.trace("SecurityIdentity=" + SecurityActions.trace(si));

                }

                //Set the security context on the invocation

                mi.setSecurityContext(sc);

            }

            else

            {

                if(log.isTraceEnabled()) {

                    log.trace("False mi.isLocal() && !isEjbTimeOutMethod");

                }

               establishSecurityContext(mi);

            }

       

            try

            {

               //Establish the run-as on the SC as the caller SC

               SecurityContext currentSC = SecurityActions.getSecurityContext();

               SecurityActions.pushCallerRunAsIdentity(currentSC.getOutgoingRunAs());

               log.trace("Going to the SecurityInterceptor with SC="+SecurityActions.trace(currentSC));

               if(isInvoke)

                  return getNext().invoke(mi);

               else

                  return getNext().invokeHome(mi);

            }

            finally

            {

               SecurityActions.popCallerRunAsIdentity();

               if(mi.isLocal()) {

                   if(si != null)

                       SecurityActions.setSecurityIdentity(SecurityActions.getSecurityContext(), si);

                   if(incomingDomain != null) {

                       SecurityActions.setSecurityDomain(SecurityActions.getSecurityContext(),

                           incomingDomain);

                       if(log.isTraceEnabled()) {

                           log.trace("restoring incoming domain to " + incomingDomain);

                       }

                   }

               }

               if(log.isTraceEnabled()) {

                   log.trace("Exit process():isInvoke=" + isInvoke);

               }

            }

         }

       

      As you can see now in case getSecurityContext returns null for sc code creates new security context for the domain. This happens when new thread created by ServletListener tries to execute Local EJB.  In the original code there was only check for sc != null and then null sc is pased which generates NPE.

       

      This error is present in both JBoss 5 and 6.

       

      I hope this will help other people with similar problems.