[
https://issues.jboss.org/browse/SECURITY-746?page=com.atlassian.jira.plug...
]
Arjan t commented on SECURITY-746:
----------------------------------
This is still a problem in WildFly 8.2, even though that one has some alignment with the
security domain of the web module (see WFLY-3102).
The code in Picketbox has changed a bit from the report, but still after JASPIC has
successfully authenticated in the web tier and then calls a method on a protected EJB,
{{org.jboss.as.ejb3.security.SecurityContextInterceptor}} still tries to authenticate with
{{org.jboss.as.security.service.SimpleSecurityManager}}.
This now happens here:
{code:java}
public class SecurityContextInterceptor implements Interceptor {
private final PrivilegedAction<Void> pushAction;
private final PrivilegedAction<Void> popAction;
public SecurityContextInterceptor(final SecurityContextInterceptorHolder holder) {
this.pushAction = new PrivilegedAction<Void>() {
@Override
public Void run() {
holder.securityManager.push(holder.securityDomain);
try {
if (holder.skipAuthentication == false) {
holder.securityManager.authenticate(holder.runAs,
holder.runAsPrincipal, holder.extraRoles);
}
if (holder.principalVsRolesMap != null) {
SecurityRolesAssociation.setSecurityRoles(holder.principalVsRolesMap);
}
} catch (Throwable t) {
{code}
{{holder.securityManager.authenticate}} will be called. This now contains the following
code:
{code:java}
private boolean authenticate(SecurityContext context, Subject subject) {
SecurityContextUtil util = context.getUtil();
SubjectInfo subjectInfo = getSubjectInfo(context);
if (subject == null) {
subject = new Subject();
}
Principal principal = util.getUserPrincipal();
Principal auditPrincipal = principal;
Object credential = util.getCredential();
Identity unauthenticatedIdentity = null;
boolean authenticated = false;
if (principal == null) {
unauthenticatedIdentity = getUnauthenticatedIdentity();
subjectInfo.addIdentity(unauthenticatedIdentity);
auditPrincipal = unauthenticatedIdentity.asPrincipal();
subject.getPrincipals().add(auditPrincipal);
authenticated = true;
} else {
subject.getPrincipals().add(principal);
}
if (authenticated == false) {
AuthenticationManager authenticationManager =
context.getAuthenticationManager();
authenticated = authenticationManager.isValid(principal, credential,
subject);
}
{code}
The 2nd line {{SubjectInfo subjectInfo = getSubjectInfo(context);}} will retrieve the
authenticated identity as established by the JASPIC auth module, but instead of using it,
it will call {{authenticationManager.isValid(principal, credential, subject);}}, which
will call through to a JAAS login module.
This will now cause the following exception:
{noformat}
javax.ejb.EJBAccessException: JBAS013323: Invalid User
at
org.jboss.as.ejb3.security.SecurityContextInterceptor$1.run(SecurityContextInterceptor.java:66)
[wildfly-ejb3-8.2.0.Final.jar:8.2.0.Final]
at
org.jboss.as.ejb3.security.SecurityContextInterceptor$1.run(SecurityContextInterceptor.java:46)
[wildfly-ejb3-8.2.0.Final.jar:8.2.0.Final]
at
org.jboss.as.ejb3.security.SecurityContextInterceptor.processInvocation(SecurityContextInterceptor.java:92)
[wildfly-ejb3-8.2.0.Final.jar:8.2.0.Final]
at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:309)
at
org.jboss.as.ejb3.component.interceptors.ShutDownInterceptorFactory$1.processInvocation(ShutDownInterceptorFactory.java:64)
[wildfly-ejb3-8.2.0.Final.jar:8.2.0.Final]
at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:309)
at
org.jboss.as.ejb3.component.interceptors.LoggingInterceptor.processInvocation(LoggingInterceptor.java:59)
[wildfly-ejb3-8.2.0.Final.jar:8.2.0.Final]
at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:309)
{noformat}
EJB SecurityContextInterceptor attempts JAAS login which doesn't
work for JASPIC authentications
------------------------------------------------------------------------------------------------
Key: SECURITY-746
URL:
https://issues.jboss.org/browse/SECURITY-746
Project: PicketBox
Issue Type: Feature Request
Reporter: arjan tijms
Assignee: Stefan Guilhen
Labels: authentication, ejb, jaspi, jaspic, security, security-context
After a user has successfully authenticated with JASPIC it's not possible to access
any method in a secured EJB bean, irrespective of the actual security constraints.
The problem is that when an EJB is "secured" an extra interceptor is added to
the chain:
{{org.jboss.as.ejb3.security.SecurityContextInterceptor.SecurityContextInterceptor}}.
This interceptor calls {{org.jboss.as.security.service.SimpleSecurityManager.push}},
which tries to establish a new stacked security context by attempting a login to a JAAS
login module associated with the security domain.
However, when the caller authenticated via a JASPIC auth module, there isn't
necessarily such a JAAS login module (the JASPIC auth module is not required to call a
JAAS login module, and even if it did it may not be the JAAS login module JBoss knows
about).
The problematic part in {{SimpleSecurityManager}}:
{code}
public void push(final String securityDomain, final String runAs, final String
runAsPrincipal, final Set<String> extraRoles) {
boolean contextPushed = false;
boolean securityContextEstablished = false;
final SecurityContext previous =
SecurityContextAssociation.getSecurityContext();
try {
contexts.push(previous);
contextPushed = true;
SecurityContext current = establishSecurityContext(securityDomain);
securityContextEstablished = true;
if (previous != null) {
current.setSubjectInfo(previous.getSubjectInfo());
current.setIncomingRunAs(previous.getOutgoingRunAs());
}
RunAs currentRunAs = current.getIncomingRunAs();
boolean trusted = currentRunAs != null && currentRunAs instanceof
RunAsIdentity;
if (trusted == false) {
boolean authenticated = false;
if (SecurityActions.remotingContextIsSet()) {
// ...
}
// If we have a trusted identity no need for a re-auth.
if (authenticated == false) {
// THIS WILL EVENTUALLY ATTEMPT A JAAS LOGIN WHICH FAILS
authenticated = authenticate(current, null);
}
{code}
The (condensed) stack that will lead to an exception is the following:
{noformat}
javax.security.auth.login.FailedLoginException: PBOX000070: Password invalid/Password
required
org.jboss.security.authentication.JBossCachedAuthenticationManager.defaultLogin(Principal,
Object)
org.jboss.security.authentication.JBossCachedAuthenticationManager.proceedWithJaasLogin(Principal,
Object, Subject)
org.jboss.security.authentication.JBossCachedAuthenticationManager.isValid(Principal,
Object, Subject)
org.jboss.as.security.service.SimpleSecurityManager.authenticate(SecurityContext,
Subject)
org.jboss.as.security.service.SimpleSecurityManager.push(String, String, String,
Set<String>)
org.jboss.as.ejb3.security.SecurityContextInterceptor.SecurityContextInterceptor(SecurityContextInterceptorHolder)
{noformat}
Since the {{SimpleSecurityManager}} is already doing a check to see if the call is remote
or not, I wonder if it could not simply accept the existing security context as-is for
local calls (not even start a new context) or just consider the existing security context
as trusted for local calls just like a {{RunAS}} identity.
Note that this depends on SECURITY-744 and SECURITY-745, since otherwise there is no
valid security context at all.
--
This message was sent by Atlassian JIRA
(v6.3.11#6341)