[I attached this comment to the JIRA issue (https://issues.apache.org/jira/browse/OPENEJB-901 ), but I think everyone may be interested, so I'm reposting it here]

I modified the OpenEJB ejb-examples for Tomcat to use a custom realm and it is working for me. Attached is the ejb-examples.war file and realm.jar. Place the war in the Tomcat webapps director and realm.jar in the Tomcat lib directory, and then visit http://localhost:8080/ejb-examples URL. Click the secure link and enter the user name manager with password manager.

Here is the code for my CustomRealm:

package org.superbiz.servlet;

import java.security.Principal;
import java.util.Arrays;

import org.apache.catalina.realm.RealmBase;
import org.apache.catalina.realm.GenericPrincipal;

public class CustomRealm extends RealmBase {
    protected String getName() {
        return "CustomRealm";
    }

    protected String getPassword(String user) {
System.out.println("CustomRealm.getPassword(" + user + ")=" + user);
        return user;
    }

    protected Principal getPrincipal(String user) {
GenericPrincipal principal = new GenericPrincipal(this, user, user, Arrays.asList(user, "user")); System.out.println("CustomRealm.getPrincipal(" + user + ")=" + principal);
        return principal;
    }
}

Basically, any user is allowed and the password is the same as the user name. The user is granted the role "user" and a role that has the same name as the user name.

The only modification I made to the ejb-example code was to add <Realm className="org.superbiz.servlet.CustomRealm"/> to the context.xml file. You can find the code for ejb-examples at https://svn.apache.org/repos/asf/openejb/trunk/openejb3/examples/webapps/ejb-examples


If you are still having problems, I will need your CustomRealm class.

-dain

On Aug 23, 2008, at 2:07 PM, Dain Sundstrom wrote:

I couldn't get he example to run because it is missing the CustomRealm class. One issue I see it the use of the OpenEJB LocalInitialContextFactory. When integrated into Tomcat JNDI ejb references and @EJB injection work automatically, so there is no need to use the LocalInitialContextFactory. This is unlikely the cause of the security problems you are seeing unless you try to login using the context. I'd just remove all the JNDI code and rely on injection... it will just work.

On Aug 22, 2008, at 4:13 PM, Dain Sundstrom wrote:

Sorry, I haven't responded earlier... been kinda off the grid lately.

This is really weird. The code is designed to pickup the real associated the web app and propagate it to the EJB container (see TomcatSecurityService.enterWebApp(Realm realm, Principal principal, String runAs). The defaultRealm in the code is only used for EJB calls from a remote VM.

As you mentioned TomcatSecurityService should override isCallerInRole() which is part of the problem you are seeing, but I'm not sure it is all of it.

After further reading, the TomcatSecurityService shouldn't override isCallerInRole. This code is very tricky, but is required by the JACC JEE spec to be implemented this way. Here is the code for the isCallerInRole method:

   public boolean isCallerInRole(String role) {
if (role == null) throw new IllegalArgumentException("Role must not be null");

       ThreadContext threadContext = ThreadContext.getThreadContext();
SecurityContext securityContext = threadContext.get(SecurityContext.class);

       try {
CoreDeploymentInfo deployment = threadContext.getDeploymentInfo();

securityContext.acc.checkPermission(new EJBRoleRefPermission(deployment.getEjbName(), role));
       } catch (AccessControlException e) {
           return false;
       }
       return true;
   }

This method redirects the isCallerInRole to a VM security check for the permission EJBRoleRefPermission. The trick is we have installed a JACC compliant java.security.Policy. When the security checkPermission method is executed, the call is redirected to BasicPolicyConfiguration.implies(ProtectionDomain, Permission) which in turn call back into the TomcatSecurityService getLogicalRoles method. This trip through the VM security lay is required by the JACC spec and gives the user a spec-compliant way to completely replace the authroization system.

The net effect is we call user.getRealm().hasRole(user.getTomcatPrincipal(), logicalRole) to determine if a user has a role. The realm is the realm we received in the OpenEJBValve when the application was entered.


I'm going to play with the security ejb-examples we have for Tomcat to see if I can reproduce the error you are seeing.

-dain



Reply via email to