[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