4 Replies Latest reply on Feb 12, 2004 2:39 PM by starksm64

    getCallerPrincipal fundamentally broken when not behind secu

    bstratford

      Problem:

      I'm finding that getCallerPrincipal returns a random result
      when accessed through a servlet using an unprotected
      (by security-constraint) servlet-mapping.

      I'm using JBoss 2.4.4 and Tomcat 4.0.1 bundle. The behavior didn't
      change when I switched to Tomcat 4.0.3 (copied in on top of 4.0.1).

      This behavior is insensitive to the LoginManager -- it's
      repeatable using both UsersRolesLoginModule and DatabaseServerLoginModule.
      I'm using FORM based authentication -- not sure if this matters.

      Test Setup:

      I have a servlet that can be accessed either through /auth or /noauth
      servlet-mapping. /auth requires authentication into the User role.

      The servlet accesses a stateless session bean and calls a single method
      ssb.getCallerPrincipal(). This method does context.getCallerPrincipal,
      prints out the result, and returns.

      Scenarios:

      1. Dangerous
      - open new browser
      - hit /noauth; getCallerPrincipal = nobody
      - hit /auth; authenticate as "joebob"; getCallerPrincipal = joebob
      - hit /noauth; hit reload 20 times quickly; getCallerPrincipal sometimes returns 'nobody', sometimes 'joebob'


      2. VERY Dangerous
      - open new browser B1 [ e.g. Mozilla ]
      - hit /auth; authenticate as "joebob"; getCallerPrincipal = joebob
      - hit /auth; hit reload 20 times quickly; getCallerPrincipal always returns 'joebob'

      - open a totally new browser B2 [ e.g. Netscape ]
      - hit /noauth; hit reload 20 times quickly; getCallerPrincipal sometimes returns 'nobody', sometimes 'joebob'



      ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
      Servlet:

      public class EJBConnectServlet extends PMBaseServlet {

      protected void processRequest(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, java.io.IOException {

      try {
      CTestFacadeHome home = (CTestFacadeHome) AppManager.getAppManager().getEJBManager().getEJBHome("CTestFacade");
      CTestFacade tf = home.create();
      tf.getCallerPrincipal();
      }
      catch (Exception e) {
      e.printStackTrace();
      }
      }
      }

      ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
      SessionBean


      public class CTestFacadeBean implements javax.ejb.SessionBean, CTestFacadeInterface {

      private transient SessionContext context = null;

      private Context getNamingContext() throws NamingException {
      Properties props = new Properties();
      props.setProperty("java.naming.factory.initial", "org.jnp.interfaces.NamingContextFactory");
      props.setProperty("java.naming.provider.url", "localhost:8099");;
      return new InitialContext(props);
      }

      public void ejbActivate() throws javax.ejb.EJBException, java.rmi.RemoteException {
      }

      public void ejbPassivate() throws javax.ejb.EJBException, java.rmi.RemoteException {
      }

      public void ejbRemove() throws javax.ejb.EJBException, java.rmi.RemoteException {
      }

      public void setSessionContext(javax.ejb.SessionContext sessionContext) throws javax.ejb.EJBException, java.rmi.RemoteException {
      context = sessionContext;
      }

      public void ejbCreate() throws CreateException, RemoteException {
      }

      public void getCallerPrincipal() throws RemoteException {
      try {
      System.out.println("test-facade::getCallerPrincipal=" + context.getCallerPrincipal().toString());
      Thread.sleep(1000);
      }
      catch (Exception e) {
      e.printStackTrace();
      }
      }

      }

      ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
      web.xml


      <servlet-name>EJBConnectServlet</servlet-name>
      <servlet-class>com.purematrix.zm.auth.servlet.EJBConnectServlet</servlet-class>


      <servlet-mapping>
      <servlet-name>EJBConnectServlet</servlet-name>
      <url-pattern>/auth</url-pattern>
      </servlet-mapping>

      <servlet-mapping>
      <servlet-name>EJBConnectServlet</servlet-name>
      <url-pattern>/noauth</url-pattern>
      </servlet-mapping>

      <security-constraint>
      <web-resource-collection>
      <web-resource-name> Require Authorization </web-resource-name>
      <url-pattern>/auth</url-pattern>
      </web-resource-collection>
      <auth-constraint>
      <role-name>User</role-name>
      </auth-constraint>
      </security-constraint>

      ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
      ejb-jar.xml


      <ejb-name>CTestFacade</ejb-name>
      com.purematrix.zm.ejb.pmi_user.CTestFacadeHome
      com.purematrix.zm.ejb.pmi_user.CTestFacade
      <ejb-class>com.purematrix.zm.ejb.pmi_user.CTestFacadeBean</ejb-class>
      <session-type>Stateless</session-type>
      <transaction-type>Container</transaction-type>


      <container-transaction>

      <ejb-name>CTestFacade</ejb-name>
      <method-name>*</method-name>

      <trans-attribute>RequiresNew</trans-attribute>
      </container-transaction>

      <method-permission>
      <role-name>User</role-name>

      <ejb-name>CTestFacade</ejb-name>
      <method-name>*</method-name>

      </method-permission>

      <method-permission>


      <ejb-name>CTestFacade</ejb-name>
      <method-name>create</method-name>


      <ejb-name>CTestFacade</ejb-name>
      <method-name>getCallerPrincipal</method-name>

      </method-permission>