Fix logout using identity. Added user defined access timeout
Project: http://git-wip-us.apache.org/repos/asf/tomee/repo Commit: http://git-wip-us.apache.org/repos/asf/tomee/commit/5c4316b5 Tree: http://git-wip-us.apache.org/repos/asf/tomee/tree/5c4316b5 Diff: http://git-wip-us.apache.org/repos/asf/tomee/diff/5c4316b5 Branch: refs/heads/tomee-1.7.x Commit: 5c4316b519581fe4d830dc5448cea918124842fa Parents: d240be6 Author: AndyGee <andy...@gmx.de> Authored: Fri Jul 3 13:41:09 2015 +0200 Committer: AndyGee <andy...@gmx.de> Committed: Fri Jul 3 13:41:09 2015 +0200 ---------------------------------------------------------------------- .../core/security/AbstractSecurityService.java | 1062 +++++----- .../core/security/SecurityServiceImpl.java | 9 +- .../openejb/ri/sp/PseudoSecurityService.java | 5 + .../org/apache/openejb/spi/SecurityService.java | 2 + .../StatefulSecurityPermissionsTest.java | 610 +++--- .../openejb/client/AuthenticationRequest.java | 269 +-- .../org/apache/openejb/client/JNDIContext.java | 1811 +++++++++--------- .../openejb/server/ejbd/AuthRequestHandler.java | 238 +-- .../tomee/catalina/TomcatSecurityService.java | 6 +- 9 files changed, 2020 insertions(+), 1992 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/tomee/blob/5c4316b5/container/openejb-core/src/main/java/org/apache/openejb/core/security/AbstractSecurityService.java ---------------------------------------------------------------------- diff --git a/container/openejb-core/src/main/java/org/apache/openejb/core/security/AbstractSecurityService.java b/container/openejb-core/src/main/java/org/apache/openejb/core/security/AbstractSecurityService.java index 0c65f24..0fad963 100644 --- a/container/openejb-core/src/main/java/org/apache/openejb/core/security/AbstractSecurityService.java +++ b/container/openejb-core/src/main/java/org/apache/openejb/core/security/AbstractSecurityService.java @@ -1,531 +1,531 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.openejb.core.security; - -import org.apache.openejb.BeanContext; -import org.apache.openejb.InterfaceType; -import org.apache.openejb.core.ThreadContext; -import org.apache.openejb.core.ThreadContextListener; -import org.apache.openejb.core.security.jaas.GroupPrincipal; -import org.apache.openejb.core.security.jacc.BasicJaccProvider; -import org.apache.openejb.core.security.jacc.BasicPolicyConfiguration; -import org.apache.openejb.loader.SystemInstance; -import org.apache.openejb.spi.CallerPrincipal; -import org.apache.openejb.spi.SecurityService; - -import javax.security.auth.Subject; -import javax.security.auth.login.LoginException; -import javax.security.jacc.EJBMethodPermission; -import javax.security.jacc.PolicyConfigurationFactory; -import javax.security.jacc.PolicyContext; -import java.io.Serializable; -import java.lang.reflect.Method; -import java.security.AccessControlContext; -import java.security.AccessControlException; -import java.security.AccessController; -import java.security.Policy; -import java.security.Principal; -import java.security.PrivilegedAction; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Enumeration; -import java.util.HashSet; -import java.util.Iterator; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Map; -import java.util.Properties; -import java.util.Set; -import java.util.Timer; -import java.util.TimerTask; -import java.util.UUID; -import java.util.concurrent.ConcurrentHashMap; - -/** - * This security service chooses a UUID as its token as this can be serialized - * to clients, is mostly secure, and can be deserialized in a client vm without - * addition openejb-core classes. - */ -public abstract class AbstractSecurityService implements SecurityService<UUID>, ThreadContextListener, BasicPolicyConfiguration.RoleResolver { - - private static final Timer timer = new Timer("AbstractSecurityService.Timer", true); - private static final Map<UUID, Identity> identities = new ConcurrentHashMap<UUID, Identity>(); - protected static final ThreadLocal<Identity> clientIdentity = new ThreadLocal<Identity>(); - protected String defaultUser = "guest"; - private String realmName = "PropertiesLogin"; - protected Subject defaultSubject; - protected SecurityContext defaultContext; - - static { - final long period = Long.parseLong(SystemInstance.get().getProperty("tomee.security.identity.schedule", "60000")); - - //TODO - Get the default session timeout rather than this - final long defaultTimeout = Long.parseLong(SystemInstance.get().getProperty("tomee.security.identity.timeout", "1800000")); - - timer.scheduleAtFixedRate(new TimerTask() { - - /** - * Check for identities that have not been accessed within timeout - */ - @Override - public void run() { - - Map.Entry<UUID, Identity> next; - final Iterator<Map.Entry<UUID, Identity>> iterator = identities.entrySet().iterator(); - while (iterator.hasNext()) { - next = iterator.next(); - final Identity value = next.getValue(); - long timeout = value.getTimeout(); - - if (0 == timeout) { - timeout = defaultTimeout; - } - - if (timeout > 0) { - if (System.currentTimeMillis() - value.getLastAccess() > timeout) { - iterator.remove(); - } - } - } - - } - }, period, period); - } - - public AbstractSecurityService() { - this(BasicJaccProvider.class.getName()); - } - - public AbstractSecurityService(final String jaccProvider) { - System.setProperty(JaccProvider.class.getName(), jaccProvider); - - installJacc(); - - ThreadContext.addThreadContextListener(this); - - // set the default subject and the default context - updateSecurityContext(); - - SystemInstance.get().setComponent(BasicPolicyConfiguration.RoleResolver.class, this); - } - - public String getRealmName() { - return realmName; - } - - public void setRealmName(final String realmName) { - this.realmName = realmName; - } - - /** - * @return the defaultUser - */ - public String getDefaultUser() { - return defaultUser; - } - - /** - * @param defaultUser the defaultUser to set - */ - @SuppressWarnings("UnusedDeclaration") - public void setDefaultUser(final String defaultUser) { - this.defaultUser = defaultUser; - - // set the default subject and the default context for the new default user - updateSecurityContext(); - } - - // update the current subject and security context - private void updateSecurityContext() { - defaultSubject = createSubject(defaultUser, defaultUser); - defaultContext = new SecurityContext(defaultSubject); - } - - @Override - public void init(final Properties props) throws Exception { - } - - @Override - public UUID login(final String username, final String password) throws LoginException { - return login(realmName, username, password); - } - - @Override - public Set<String> getLogicalRoles(final Principal[] principals, final Set<String> logicalRoles) { - final LinkedHashSet<String> roles = new LinkedHashSet<String>(principals.length); - for (final Principal principal : principals) { - final String name = principal.getName(); - if (logicalRoles.contains(name)) { - roles.add(name); - } - } - return roles; - } - - @Override - public void contextEntered(final ThreadContext oldContext, final ThreadContext newContext) { - final String moduleID = newContext.getBeanContext().getModuleID(); - PolicyContext.setContextID(moduleID); - - Subject runAsSubject = getRunAsSubject(newContext.getBeanContext()); - if (oldContext != null && runAsSubject == null) { - runAsSubject = getRunAsSubject(oldContext.getBeanContext()); - } - - SecurityContext securityContext = oldContext != null ? oldContext.get(SecurityContext.class) : null; - if (runAsSubject != null) { - - securityContext = new SecurityContext(runAsSubject); - - } else if (securityContext == null) { - - final Identity identity = clientIdentity.get(); - if (identity != null) { - securityContext = new SecurityContext(identity.subject); - } else { - securityContext = defaultContext; - } - } - - newContext.set(SecurityContext.class, securityContext); - } - - protected Subject getRunAsSubject(final BeanContext callingBeanContext) { - if (callingBeanContext == null) { - return null; - } - return createRunAsSubject(callingBeanContext.getRunAsUser(), callingBeanContext.getRunAs()); - } - - protected Subject createRunAsSubject(final String runAsUser, final String runAsRole) { - return createSubject(runAsUser, runAsRole); - } - - @Override - public void contextExited(final ThreadContext exitedContext, final ThreadContext reenteredContext) { - if (reenteredContext == null) { - PolicyContext.setContextID(null); - } else { - PolicyContext.setContextID(reenteredContext.getBeanContext().getModuleID()); - } - } - - protected UUID registerSubject(final Subject subject) { - final Identity identity = new Identity(subject); - final UUID token = identity.getToken(); - identities.put(token, identity); - return token; - } - - @Override - public void logout(final UUID securityIdentity) throws LoginException { - final Identity identity = identities.get(securityIdentity); - if (identity == null) { - throw new LoginException("Identity is not currently logged in: " + securityIdentity); - } - identities.remove(securityIdentity); - } - - @SuppressWarnings("UnusedDeclaration") - protected void unregisterSubject(final Object securityIdentity) { - identities.remove(UUID.class.cast(securityIdentity)); - } - - @Override - public void associate(final UUID securityIdentity) throws LoginException { - if (clientIdentity.get() != null) { - throw new LoginException("Thread already associated with a client identity. Refusing to overwrite."); - } - if (securityIdentity == null) { - throw new NullPointerException("The security token passed in is null"); - } - - // The securityIdentity token must associated with a logged in Identity - final Identity identity = identities.get(securityIdentity); - if (identity == null) { - throw new LoginException("Identity is not currently logged in: " + securityIdentity); - } - - clientIdentity.set(identity); - } - - @Override - public UUID disassociate() { - try { - final Identity identity = clientIdentity.get(); - return identity == null ? null : identity.getToken(); - } finally { - clientIdentity.remove(); - } - } - - @Override - public boolean isCallerInRole(final String role) { - if (role == null) { - throw new IllegalArgumentException("Role must not be null"); - } - - final ThreadContext threadContext = ThreadContext.getThreadContext(); - if (threadContext == null) { - return false; - } - - final SecurityContext securityContext = threadContext.get(SecurityContext.class); - - final Set<Group> grps = securityContext.subject.getPrincipals(Group.class); - for (final Group grp : grps) { - if (grp.getName().equals(role)) { - return true; - } - } - final Set<GroupPrincipal> grpsp = securityContext.subject.getPrincipals(GroupPrincipal.class); - for (final GroupPrincipal grp : grpsp) { - if (grp.getName().equals(role)) { - return true; - } - } - return false; - } - - @Override - public Principal getCallerPrincipal() { - final ThreadContext threadContext = ThreadContext.getThreadContext(); - if (threadContext == null) { - final Identity id = clientIdentity.get(); - if (id != null) { - return getCallerPrincipal(id.getSubject().getPrincipals()); - } - return null; - } - - final SecurityContext securityContext = threadContext.get(SecurityContext.class); - final Set<Principal> principals = securityContext.subject.getPrincipals(); - return getCallerPrincipal(principals); - } - - private Principal getCallerPrincipal(final Set<Principal> principals) { - if (!principals.isEmpty()) { - for (final Principal principal : principals) { - if (principal.getClass().isAnnotationPresent(CallerPrincipal.class)) { - return principal; - } - } - return principals.iterator().next(); - } - return null; - } - - @Override - public boolean isCallerAuthorized(final Method method, final InterfaceType type) { - final ThreadContext threadContext = ThreadContext.getThreadContext(); - final BeanContext beanContext = threadContext.getBeanContext(); - try { - final String ejbName = beanContext.getEjbName(); - String name = type == null ? null : type.getSpecName(); - if ("LocalBean".equals(name) || "LocalBeanHome".equals(name)) { - name = null; - } - final Identity currentIdentity = clientIdentity.get(); - final SecurityContext securityContext; - if (currentIdentity == null) { - securityContext = threadContext.get(SecurityContext.class); - } else { - securityContext = new SecurityContext(currentIdentity.getSubject()); - } - securityContext.acc.checkPermission(new EJBMethodPermission(ejbName, name, method)); - } catch (final AccessControlException e) { - return false; - } - return true; - } - - protected static void installJacc() { - final ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader(); - - final String providerKey = "javax.security.jacc.PolicyConfigurationFactory.provider"; - try { - if (System.getProperty(providerKey) == null) { - System.setProperty(providerKey, JaccProvider.Factory.class.getName()); - final ClassLoader cl = JaccProvider.Factory.class.getClassLoader(); - Thread.currentThread().setContextClassLoader(cl); - } - - // Force the loading of the javax.security.jacc.PolicyConfigurationFactory.provider - // Hopefully it will be cached thereafter and ClassNotFoundExceptions thrown - // from the equivalent call in JaccPermissionsBuilder can be avoided. - PolicyConfigurationFactory.getPolicyConfigurationFactory(); - } catch (final Exception e) { - throw new IllegalStateException("Could not install JACC Policy Configuration Factory: " + System.getProperty(providerKey), e); - } finally { - Thread.currentThread().setContextClassLoader(contextClassLoader); - } - - final String policyProvider = SystemInstance.get().getOptions().get("javax.security.jacc.policy.provider", JaccProvider.Policy.class.getName()); - try { - final ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); - final Class policyClass = Class.forName(policyProvider, true, classLoader); - final Policy policy = (Policy) policyClass.newInstance(); - policy.refresh(); - Policy.setPolicy(policy); - } catch (final Exception e) { - throw new IllegalStateException("Could not install JACC Policy Provider: " + policyProvider, e); - } - } - - protected Subject createSubject(final String name, final String groupName) { - if (name == null) { - return null; - } - - final User user = new User(name); - final Group group = new Group(groupName); - group.addMember(user); - - final HashSet<Principal> principals = new HashSet<Principal>(); - principals.add(user); - principals.add(group); - - return new Subject(true, principals, new HashSet(), new HashSet()); - } - - @Override - public Object currentState() { - return clientIdentity.get(); - } - - @Override - public void setState(final Object o) { - if (Identity.class.isInstance(o)) { - clientIdentity.set(Identity.class.cast(o)); - } else if (o == null) { - clientIdentity.remove(); - } - } - - protected static final class SecurityContext { - - public final Subject subject; - public final AccessControlContext acc; - - @SuppressWarnings("unchecked") - public SecurityContext(final Subject subject) { - this.subject = subject; - this.acc = (AccessControlContext) Subject.doAsPrivileged(subject, new PrivilegedAction() { - @Override - public Object run() { - return AccessController.getContext(); - } - }, null); - } - } - - protected static class Identity implements Serializable { - - private long lastAccess; - private long timeout; - private final Subject subject; - private final UUID token; - - public Identity(final Subject subject) { - this.subject = subject; - this.token = UUID.randomUUID(); - access(); - } - - public Identity(final Subject subject, final UUID token) { - this.subject = subject; - this.token = token; - } - - private void access() { - this.lastAccess = System.currentTimeMillis(); - } - - public Subject getSubject() { - access(); - return subject; - } - - public UUID getToken() { - access(); - return token; - } - - public long getLastAccess() { - return lastAccess; - } - - public void setTimeout(final long timeout) { - this.timeout = timeout; - } - - public long getTimeout() { - return timeout; - } - } - - public static class Group implements java.security.acl.Group { - - private final List<Principal> members = new ArrayList<Principal>(); - private final String name; - - public Group(final String name) { - this.name = name; - } - - @Override - public boolean addMember(final Principal user) { - return members.add(user); - } - - @Override - public boolean removeMember(final Principal user) { - return members.remove(user); - } - - @Override - public boolean isMember(final Principal member) { - return members.contains(member); - } - - @Override - public Enumeration<? extends Principal> members() { - return Collections.enumeration(members); - } - - @Override - public String getName() { - return name; - } - } - - @CallerPrincipal // to force it to be before group in getCallerPrincipal, otherwise we aren't deterministic - public static class User implements Principal { - - private final String name; - - public User(final String name) { - this.name = name; - } - - @Override - public String getName() { - return name; - } - } -} +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.openejb.core.security; + +import org.apache.openejb.BeanContext; +import org.apache.openejb.InterfaceType; +import org.apache.openejb.core.ThreadContext; +import org.apache.openejb.core.ThreadContextListener; +import org.apache.openejb.core.security.jaas.GroupPrincipal; +import org.apache.openejb.core.security.jacc.BasicJaccProvider; +import org.apache.openejb.core.security.jacc.BasicPolicyConfiguration; +import org.apache.openejb.loader.SystemInstance; +import org.apache.openejb.spi.CallerPrincipal; +import org.apache.openejb.spi.SecurityService; + +import javax.security.auth.Subject; +import javax.security.auth.login.LoginException; +import javax.security.jacc.EJBMethodPermission; +import javax.security.jacc.PolicyConfigurationFactory; +import javax.security.jacc.PolicyContext; +import java.io.Serializable; +import java.lang.reflect.Method; +import java.security.AccessControlContext; +import java.security.AccessControlException; +import java.security.AccessController; +import java.security.Policy; +import java.security.Principal; +import java.security.PrivilegedAction; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Enumeration; +import java.util.HashSet; +import java.util.Iterator; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; +import java.util.Properties; +import java.util.Set; +import java.util.Timer; +import java.util.TimerTask; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; + +/** + * This security service chooses a UUID as its token as this can be serialized + * to clients, is mostly secure, and can be deserialized in a client vm without + * addition openejb-core classes. + */ +public abstract class AbstractSecurityService implements SecurityService<UUID>, ThreadContextListener, BasicPolicyConfiguration.RoleResolver { + + private static final Timer timer = new Timer("AbstractSecurityService.Timer", true); + private static final Map<UUID, Identity> identities = new ConcurrentHashMap<UUID, Identity>(); + protected static final ThreadLocal<Identity> clientIdentity = new ThreadLocal<Identity>(); + protected String defaultUser = "guest"; + private String realmName = "PropertiesLogin"; + protected Subject defaultSubject; + protected SecurityContext defaultContext; + + static { + final long period = Long.parseLong(SystemInstance.get().getProperty("tomee.security.identity.schedule", "60000")); + + //TODO - Get the default session timeout rather than this + final long defaultTimeout = Long.parseLong(SystemInstance.get().getProperty("tomee.security.identity.timeout", "1800000")); + + timer.scheduleAtFixedRate(new TimerTask() { + + /** + * Check for identities that have not been accessed within timeout + */ + @Override + public void run() { + + Map.Entry<UUID, Identity> next; + final Iterator<Map.Entry<UUID, Identity>> iterator = identities.entrySet().iterator(); + while (iterator.hasNext()) { + next = iterator.next(); + final Identity value = next.getValue(); + long timeout = value.getTimeout(); + + if (0 == timeout) { + timeout = defaultTimeout; + } + + if (timeout > 0) { + if (System.currentTimeMillis() - value.getLastAccess() > timeout) { + iterator.remove(); + } + } + } + + } + }, period, period); + } + + public AbstractSecurityService() { + this(BasicJaccProvider.class.getName()); + } + + public AbstractSecurityService(final String jaccProvider) { + System.setProperty(JaccProvider.class.getName(), jaccProvider); + + installJacc(); + + ThreadContext.addThreadContextListener(this); + + // set the default subject and the default context + updateSecurityContext(); + + SystemInstance.get().setComponent(BasicPolicyConfiguration.RoleResolver.class, this); + } + + public String getRealmName() { + return realmName; + } + + public void setRealmName(final String realmName) { + this.realmName = realmName; + } + + /** + * @return the defaultUser + */ + public String getDefaultUser() { + return defaultUser; + } + + /** + * @param defaultUser the defaultUser to set + */ + @SuppressWarnings("UnusedDeclaration") + public void setDefaultUser(final String defaultUser) { + this.defaultUser = defaultUser; + + // set the default subject and the default context for the new default user + updateSecurityContext(); + } + + // update the current subject and security context + private void updateSecurityContext() { + defaultSubject = createSubject(defaultUser, defaultUser); + defaultContext = new SecurityContext(defaultSubject); + } + + @Override + public void init(final Properties props) throws Exception { + } + + @Override + public UUID login(final String username, final String password) throws LoginException { + return login(realmName, username, password); + } + + @Override + public Set<String> getLogicalRoles(final Principal[] principals, final Set<String> logicalRoles) { + final LinkedHashSet<String> roles = new LinkedHashSet<String>(principals.length); + for (final Principal principal : principals) { + final String name = principal.getName(); + if (logicalRoles.contains(name)) { + roles.add(name); + } + } + return roles; + } + + @Override + public void contextEntered(final ThreadContext oldContext, final ThreadContext newContext) { + final String moduleID = newContext.getBeanContext().getModuleID(); + PolicyContext.setContextID(moduleID); + + Subject runAsSubject = getRunAsSubject(newContext.getBeanContext()); + if (oldContext != null && runAsSubject == null) { + runAsSubject = getRunAsSubject(oldContext.getBeanContext()); + } + + SecurityContext securityContext = oldContext != null ? oldContext.get(SecurityContext.class) : null; + if (runAsSubject != null) { + + securityContext = new SecurityContext(runAsSubject); + + } else if (securityContext == null) { + + final Identity identity = clientIdentity.get(); + if (identity != null) { + securityContext = new SecurityContext(identity.subject); + } else { + securityContext = defaultContext; + } + } + + newContext.set(SecurityContext.class, securityContext); + } + + protected Subject getRunAsSubject(final BeanContext callingBeanContext) { + if (callingBeanContext == null) { + return null; + } + return createRunAsSubject(callingBeanContext.getRunAsUser(), callingBeanContext.getRunAs()); + } + + protected Subject createRunAsSubject(final String runAsUser, final String runAsRole) { + return createSubject(runAsUser, runAsRole); + } + + @Override + public void contextExited(final ThreadContext exitedContext, final ThreadContext reenteredContext) { + if (reenteredContext == null) { + PolicyContext.setContextID(null); + } else { + PolicyContext.setContextID(reenteredContext.getBeanContext().getModuleID()); + } + } + + protected UUID registerSubject(final Subject subject, final long accessTimeout) { + final Identity identity = new Identity(subject); + final UUID token = identity.getToken(); + identities.put(token, identity); + return token; + } + + @Override + public void logout(final UUID securityIdentity) throws LoginException { + final Identity identity = identities.get(securityIdentity); + if (identity == null) { + throw new LoginException("Identity is not currently logged in: " + securityIdentity); + } + identities.remove(securityIdentity); + } + + @SuppressWarnings("UnusedDeclaration") + protected void unregisterSubject(final Object securityIdentity) { + identities.remove(UUID.class.cast(securityIdentity)); + } + + @Override + public void associate(final UUID securityIdentity) throws LoginException { + if (clientIdentity.get() != null) { + throw new LoginException("Thread already associated with a client identity. Refusing to overwrite."); + } + if (securityIdentity == null) { + throw new NullPointerException("The security token passed in is null"); + } + + // The securityIdentity token must associated with a logged in Identity + final Identity identity = identities.get(securityIdentity); + if (identity == null) { + throw new LoginException("Identity is not currently logged in: " + securityIdentity); + } + + clientIdentity.set(identity); + } + + @Override + public UUID disassociate() { + try { + final Identity identity = clientIdentity.get(); + return identity == null ? null : identity.getToken(); + } finally { + clientIdentity.remove(); + } + } + + @Override + public boolean isCallerInRole(final String role) { + if (role == null) { + throw new IllegalArgumentException("Role must not be null"); + } + + final ThreadContext threadContext = ThreadContext.getThreadContext(); + if (threadContext == null) { + return false; + } + + final SecurityContext securityContext = threadContext.get(SecurityContext.class); + + final Set<Group> grps = securityContext.subject.getPrincipals(Group.class); + for (final Group grp : grps) { + if (grp.getName().equals(role)) { + return true; + } + } + final Set<GroupPrincipal> grpsp = securityContext.subject.getPrincipals(GroupPrincipal.class); + for (final GroupPrincipal grp : grpsp) { + if (grp.getName().equals(role)) { + return true; + } + } + return false; + } + + @Override + public Principal getCallerPrincipal() { + final ThreadContext threadContext = ThreadContext.getThreadContext(); + if (threadContext == null) { + final Identity id = clientIdentity.get(); + if (id != null) { + return getCallerPrincipal(id.getSubject().getPrincipals()); + } + return null; + } + + final SecurityContext securityContext = threadContext.get(SecurityContext.class); + final Set<Principal> principals = securityContext.subject.getPrincipals(); + return getCallerPrincipal(principals); + } + + private Principal getCallerPrincipal(final Set<Principal> principals) { + if (!principals.isEmpty()) { + for (final Principal principal : principals) { + if (principal.getClass().isAnnotationPresent(CallerPrincipal.class)) { + return principal; + } + } + return principals.iterator().next(); + } + return null; + } + + @Override + public boolean isCallerAuthorized(final Method method, final InterfaceType type) { + final ThreadContext threadContext = ThreadContext.getThreadContext(); + final BeanContext beanContext = threadContext.getBeanContext(); + try { + final String ejbName = beanContext.getEjbName(); + String name = type == null ? null : type.getSpecName(); + if ("LocalBean".equals(name) || "LocalBeanHome".equals(name)) { + name = null; + } + final Identity currentIdentity = clientIdentity.get(); + final SecurityContext securityContext; + if (currentIdentity == null) { + securityContext = threadContext.get(SecurityContext.class); + } else { + securityContext = new SecurityContext(currentIdentity.getSubject()); + } + securityContext.acc.checkPermission(new EJBMethodPermission(ejbName, name, method)); + } catch (final AccessControlException e) { + return false; + } + return true; + } + + protected static void installJacc() { + final ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader(); + + final String providerKey = "javax.security.jacc.PolicyConfigurationFactory.provider"; + try { + if (System.getProperty(providerKey) == null) { + System.setProperty(providerKey, JaccProvider.Factory.class.getName()); + final ClassLoader cl = JaccProvider.Factory.class.getClassLoader(); + Thread.currentThread().setContextClassLoader(cl); + } + + // Force the loading of the javax.security.jacc.PolicyConfigurationFactory.provider + // Hopefully it will be cached thereafter and ClassNotFoundExceptions thrown + // from the equivalent call in JaccPermissionsBuilder can be avoided. + PolicyConfigurationFactory.getPolicyConfigurationFactory(); + } catch (final Exception e) { + throw new IllegalStateException("Could not install JACC Policy Configuration Factory: " + System.getProperty(providerKey), e); + } finally { + Thread.currentThread().setContextClassLoader(contextClassLoader); + } + + final String policyProvider = SystemInstance.get().getOptions().get("javax.security.jacc.policy.provider", JaccProvider.Policy.class.getName()); + try { + final ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); + final Class policyClass = Class.forName(policyProvider, true, classLoader); + final Policy policy = (Policy) policyClass.newInstance(); + policy.refresh(); + Policy.setPolicy(policy); + } catch (final Exception e) { + throw new IllegalStateException("Could not install JACC Policy Provider: " + policyProvider, e); + } + } + + protected Subject createSubject(final String name, final String groupName) { + if (name == null) { + return null; + } + + final User user = new User(name); + final Group group = new Group(groupName); + group.addMember(user); + + final HashSet<Principal> principals = new HashSet<Principal>(); + principals.add(user); + principals.add(group); + + return new Subject(true, principals, new HashSet(), new HashSet()); + } + + @Override + public Object currentState() { + return clientIdentity.get(); + } + + @Override + public void setState(final Object o) { + if (Identity.class.isInstance(o)) { + clientIdentity.set(Identity.class.cast(o)); + } else if (o == null) { + clientIdentity.remove(); + } + } + + protected static final class SecurityContext { + + public final Subject subject; + public final AccessControlContext acc; + + @SuppressWarnings("unchecked") + public SecurityContext(final Subject subject) { + this.subject = subject; + this.acc = (AccessControlContext) Subject.doAsPrivileged(subject, new PrivilegedAction() { + @Override + public Object run() { + return AccessController.getContext(); + } + }, null); + } + } + + protected static class Identity implements Serializable { + + private long lastAccess; + private long timeout; + private final Subject subject; + private final UUID token; + + public Identity(final Subject subject) { + this.subject = subject; + this.token = UUID.randomUUID(); + access(); + } + + public Identity(final Subject subject, final UUID token) { + this.subject = subject; + this.token = token; + } + + private void access() { + this.lastAccess = System.currentTimeMillis(); + } + + public Subject getSubject() { + access(); + return subject; + } + + public UUID getToken() { + access(); + return token; + } + + public long getLastAccess() { + return lastAccess; + } + + public void setTimeout(final long timeout) { + this.timeout = timeout; + } + + public long getTimeout() { + return timeout; + } + } + + public static class Group implements java.security.acl.Group { + + private final List<Principal> members = new ArrayList<Principal>(); + private final String name; + + public Group(final String name) { + this.name = name; + } + + @Override + public boolean addMember(final Principal user) { + return members.add(user); + } + + @Override + public boolean removeMember(final Principal user) { + return members.remove(user); + } + + @Override + public boolean isMember(final Principal member) { + return members.contains(member); + } + + @Override + public Enumeration<? extends Principal> members() { + return Collections.enumeration(members); + } + + @Override + public String getName() { + return name; + } + } + + @CallerPrincipal // to force it to be before group in getCallerPrincipal, otherwise we aren't deterministic + public static class User implements Principal { + + private final String name; + + public User(final String name) { + this.name = name; + } + + @Override + public String getName() { + return name; + } + } +} http://git-wip-us.apache.org/repos/asf/tomee/blob/5c4316b5/container/openejb-core/src/main/java/org/apache/openejb/core/security/SecurityServiceImpl.java ---------------------------------------------------------------------- diff --git a/container/openejb-core/src/main/java/org/apache/openejb/core/security/SecurityServiceImpl.java b/container/openejb-core/src/main/java/org/apache/openejb/core/security/SecurityServiceImpl.java index dd942c4..3eec427 100644 --- a/container/openejb-core/src/main/java/org/apache/openejb/core/security/SecurityServiceImpl.java +++ b/container/openejb-core/src/main/java/org/apache/openejb/core/security/SecurityServiceImpl.java @@ -77,7 +77,12 @@ public class SecurityServiceImpl extends AbstractSecurityService { } @Override - public UUID login(String realmName, final String username, final String password) throws LoginException { + public UUID login(final String securityRealm, final String user, final String pass) throws LoginException { + return this.login(securityRealm, user, pass, 0); + } + + @Override + public UUID login(String realmName, final String username, final String password, final long accessTimeout) throws LoginException { if (realmName == null) { realmName = getRealmName(); } @@ -86,7 +91,7 @@ public class SecurityServiceImpl extends AbstractSecurityService { final Subject subject = context.getSubject(); - final UUID token = registerSubject(subject); + final UUID token = registerSubject(subject, accessTimeout); contexts.put(token, context); return token; http://git-wip-us.apache.org/repos/asf/tomee/blob/5c4316b5/container/openejb-core/src/main/java/org/apache/openejb/ri/sp/PseudoSecurityService.java ---------------------------------------------------------------------- diff --git a/container/openejb-core/src/main/java/org/apache/openejb/ri/sp/PseudoSecurityService.java b/container/openejb-core/src/main/java/org/apache/openejb/ri/sp/PseudoSecurityService.java index 0f1bc54..b93f5f9 100644 --- a/container/openejb-core/src/main/java/org/apache/openejb/ri/sp/PseudoSecurityService.java +++ b/container/openejb-core/src/main/java/org/apache/openejb/ri/sp/PseudoSecurityService.java @@ -46,6 +46,11 @@ public class PseudoSecurityService implements SecurityService { return null; } + @Override + public Object login(final String securityRealm, final String user, final String pass, final long accessTimeout) throws LoginException { + return null; + } + public Set<String> getLogicalRoles(final Principal[] principals, final Set<String> logicalRoles) { return Collections.emptySet(); } http://git-wip-us.apache.org/repos/asf/tomee/blob/5c4316b5/container/openejb-core/src/main/java/org/apache/openejb/spi/SecurityService.java ---------------------------------------------------------------------- diff --git a/container/openejb-core/src/main/java/org/apache/openejb/spi/SecurityService.java b/container/openejb-core/src/main/java/org/apache/openejb/spi/SecurityService.java index a5840da..40bee8f 100644 --- a/container/openejb-core/src/main/java/org/apache/openejb/spi/SecurityService.java +++ b/container/openejb-core/src/main/java/org/apache/openejb/spi/SecurityService.java @@ -39,6 +39,8 @@ public interface SecurityService<T> extends Service { T login(String securityRealm, String user, String pass) throws LoginException; + T login(String securityRealm, String user, String pass, long accessTimeout) throws LoginException; + /** * Active */ http://git-wip-us.apache.org/repos/asf/tomee/blob/5c4316b5/container/openejb-core/src/test/java/org/apache/openejb/core/stateful/StatefulSecurityPermissionsTest.java ---------------------------------------------------------------------- diff --git a/container/openejb-core/src/test/java/org/apache/openejb/core/stateful/StatefulSecurityPermissionsTest.java b/container/openejb-core/src/test/java/org/apache/openejb/core/stateful/StatefulSecurityPermissionsTest.java index db3bc32..2fecc81 100644 --- a/container/openejb-core/src/test/java/org/apache/openejb/core/stateful/StatefulSecurityPermissionsTest.java +++ b/container/openejb-core/src/test/java/org/apache/openejb/core/stateful/StatefulSecurityPermissionsTest.java @@ -1,302 +1,308 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.openejb.core.stateful; - -import junit.framework.TestCase; -import org.apache.openejb.OpenEJB; -import org.apache.openejb.assembler.classic.Assembler; -import org.apache.openejb.assembler.classic.EjbJarInfo; -import org.apache.openejb.assembler.classic.ProxyFactoryInfo; -import org.apache.openejb.assembler.classic.SecurityServiceInfo; -import org.apache.openejb.assembler.classic.TransactionServiceInfo; -import org.apache.openejb.config.ConfigurationFactory; -import org.apache.openejb.core.ivm.naming.InitContextFactory; -import org.apache.openejb.core.security.AbstractSecurityService; -import org.apache.openejb.core.security.jaas.GroupPrincipal; -import org.apache.openejb.core.security.jaas.UserPrincipal; -import org.apache.openejb.core.security.jacc.BasicJaccProvider; -import org.apache.openejb.core.security.jacc.BasicPolicyConfiguration; -import org.apache.openejb.jee.EjbJar; -import org.apache.openejb.jee.MethodPermission; -import org.apache.openejb.jee.StatefulBean; -import org.apache.openejb.loader.SystemInstance; -import org.apache.openejb.spi.SecurityService; -import org.junit.AfterClass; - -import javax.annotation.security.DenyAll; -import javax.annotation.security.PermitAll; -import javax.annotation.security.RolesAllowed; -import javax.ejb.CreateException; -import javax.ejb.EJBAccessException; -import javax.ejb.EJBHome; -import javax.ejb.EJBLocalHome; -import javax.ejb.EJBLocalObject; -import javax.ejb.EJBObject; -import javax.ejb.Init; -import javax.ejb.Local; -import javax.ejb.LocalHome; -import javax.ejb.Remote; -import javax.ejb.RemoteHome; -import javax.ejb.Remove; -import javax.naming.InitialContext; -import javax.security.auth.Subject; -import javax.security.auth.login.LoginException; -import java.rmi.RemoteException; -import java.security.Permission; -import java.security.PermissionCollection; -import java.security.Principal; -import java.security.ProtectionDomain; -import java.util.Collections; -import java.util.HashSet; -import java.util.List; -import java.util.Set; -import java.util.UUID; - -/** - * @version $Rev$ $Date$ - */ -public class StatefulSecurityPermissionsTest extends TestCase { - - @AfterClass - public static void afterClass() throws Exception { - OpenEJB.destroy(); - } - - public void test() throws Exception { - System.setProperty(javax.naming.Context.INITIAL_CONTEXT_FACTORY, InitContextFactory.class.getName()); - - final Assembler assembler = new Assembler(); - final ConfigurationFactory config = new ConfigurationFactory(); - - assembler.createProxyFactory(config.configureService(ProxyFactoryInfo.class)); - assembler.createTransactionManager(config.configureService(TransactionServiceInfo.class)); - final SecurityServiceInfo securityServiceInfo = config.configureService(SecurityServiceInfo.class); - securityServiceInfo.className = TestSecurityService.class.getName(); - assembler.createSecurityService(securityServiceInfo); - - final TestSecurityService securityService = (TestSecurityService) SystemInstance.get().getComponent(SecurityService.class); - - securityService.login("foo", "Jazz", "Rock", "Reggae", "HipHop"); - - final EjbJar ejbJar = new EjbJar(); - ejbJar.addEnterpriseBean(new StatefulBean(Color.class)); - final List<MethodPermission> permissions = ejbJar.getAssemblyDescriptor().getMethodPermission(); - permissions.add(new MethodPermission("*", "Color", "*", "Foo")); - permissions.add(new MethodPermission("*", "Color", "create").setUnchecked()); - permissions.add(new MethodPermission("*", "Color", "ejbCreate").setUnchecked()); - - final EjbJarInfo ejbJarInfo = config.configureApplication(ejbJar); - assembler.createApplication(ejbJarInfo); - - final InitialContext context = new InitialContext(); - - { - final ColorLocal color = (ColorLocal) context.lookup("ColorLocal"); - - assertEquals("Jazz", color.color()); - try { - color.color((Object) null); - } catch (final EJBAccessException e) { - assertEquals("Excluded", actual.get()); - } - assertEquals("Rock", color.color((String) null)); - assertEquals("Unchecked", color.color((Boolean) null)); - assertEquals("Reggae", color.color((Integer) null)); - } - - } - - public static ThreadLocal<String> expected = new ThreadLocal<String>(); - - @LocalHome(ColorEjbLocalHome.class) - @RemoteHome(ColorEjbHome.class) - public static class Color implements ColorLocal, ColorRemote { - - protected String attribute() { - return actual.get(); - } - - @Init - public void ejbCreate(final String s) { - assertEquals(s, attribute()); - } - - @Remove - public void ejbRemove() { - assertEquals(expected.get(), attribute()); - } - - - @RolesAllowed({"Jazz"}) - public String color() { - return attribute(); - } - - @DenyAll - public String color(final Object o) { - return attribute(); - } - - @RolesAllowed({"Rock"}) - public String color(final String s) { - return attribute(); - } - - @PermitAll - public String color(final Boolean b) { - return attribute(); - } - - @RolesAllowed({"Reggae"}) - public String color(final Integer i) { - return attribute(); - } - - - } - - @Local - public static interface ColorLocal { - public String color(); - - public String color(Object o); - - public String color(String s); - - public String color(Boolean b); - - public String color(Integer i); - } - - @Remote - public static interface ColorRemote { - public String color(); - - public String color(Object o); - - public String color(String s); - - public String color(Boolean b); - - public String color(Integer i); - } - - public static interface ColorEjbHome extends EJBHome { - ColorEjbObject create(String s) throws CreateException, RemoteException; - } - - public static interface ColorEjbObject extends EJBObject { - public String color() throws RemoteException; - - public String color(Object o) throws RemoteException; - - public String color(String s) throws RemoteException; - - public String color(Boolean b) throws RemoteException; - - public String color(Integer i) throws RemoteException; - } - - public static interface ColorEjbLocalHome extends EJBLocalHome { - ColorEjbLocalObject create(String s) throws CreateException; - } - - public static interface ColorEjbLocalObject extends EJBLocalObject { - public String color(); - - public String color(Object o); - - public String color(String s); - - public String color(Boolean b); - - public String color(Integer i); - } - - - private static final ThreadLocal<String> actual = new ThreadLocal<String>(); - - public static class TestSecurityService extends AbstractSecurityService { - - public TestSecurityService() { - super(TestJaccProvider.class.getName()); - } - - public UUID login(final String securityRealm, final String user, final String pass) throws LoginException { - return null; - } - - public void login(final String user, final String... roles) throws LoginException { - final Set<Principal> set = new HashSet<Principal>(); - set.add(new UserPrincipal(user)); - for (final String role : roles) { - set.add(new GroupPrincipal(role)); - } - final Subject subject = new Subject(true, set, Collections.EMPTY_SET, Collections.EMPTY_SET); - final UUID uuid = registerSubject(subject); - associate(uuid); - } - - public void logout() { - this.disassociate(); - } - - public static class TestJaccProvider extends BasicJaccProvider { - protected BasicPolicyConfiguration createPolicyConfiguration(final String contextID) { - return new TestPolicy(contextID); - } - - public static class TestPolicy extends BasicPolicyConfiguration { - - TestPolicy(final String contextID) { - super(contextID); - } - - public boolean implies(final ProtectionDomain domain, final Permission permission) { - - if (excluded != null && excluded.implies(permission)) { - actual.set("Excluded"); - return false; - } - - if (unchecked != null && unchecked.implies(permission)) { - actual.set("Unchecked"); - return true; - } - - final Principal[] principals = domain.getPrincipals(); - if (principals.length == 0) return false; - - final RoleResolver roleResolver = SystemInstance.get().getComponent(RoleResolver.class); - final Set<String> roles = roleResolver.getLogicalRoles(principals, rolePermissionsMap.keySet()); - - for (final String role : roles) { - final PermissionCollection permissions = rolePermissionsMap.get(role); - - if (permissions != null && permissions.implies(permission)) { - actual.set(role); - return true; - } - } - - actual.set("Denied"); - return false; - } - } - } - } -} +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.openejb.core.stateful; + +import junit.framework.TestCase; +import org.apache.openejb.OpenEJB; +import org.apache.openejb.assembler.classic.Assembler; +import org.apache.openejb.assembler.classic.EjbJarInfo; +import org.apache.openejb.assembler.classic.ProxyFactoryInfo; +import org.apache.openejb.assembler.classic.SecurityServiceInfo; +import org.apache.openejb.assembler.classic.TransactionServiceInfo; +import org.apache.openejb.config.ConfigurationFactory; +import org.apache.openejb.core.security.AbstractSecurityService; +import org.apache.openejb.core.security.jaas.GroupPrincipal; +import org.apache.openejb.core.security.jaas.UserPrincipal; +import org.apache.openejb.core.security.jacc.BasicJaccProvider; +import org.apache.openejb.core.security.jacc.BasicPolicyConfiguration; +import org.apache.openejb.jee.EjbJar; +import org.apache.openejb.jee.MethodPermission; +import org.apache.openejb.jee.StatefulBean; +import org.apache.openejb.loader.SystemInstance; +import org.apache.openejb.spi.SecurityService; +import org.junit.AfterClass; + +import javax.annotation.security.DenyAll; +import javax.annotation.security.PermitAll; +import javax.annotation.security.RolesAllowed; +import javax.ejb.CreateException; +import javax.ejb.EJBAccessException; +import javax.ejb.EJBHome; +import javax.ejb.EJBLocalHome; +import javax.ejb.EJBLocalObject; +import javax.ejb.EJBObject; +import javax.ejb.Init; +import javax.ejb.Local; +import javax.ejb.LocalHome; +import javax.ejb.Remote; +import javax.ejb.RemoteHome; +import javax.ejb.Remove; +import javax.naming.InitialContext; +import javax.security.auth.Subject; +import javax.security.auth.login.LoginException; +import java.rmi.RemoteException; +import java.security.Permission; +import java.security.PermissionCollection; +import java.security.Principal; +import java.security.ProtectionDomain; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.UUID; + +/** + * @version $Rev$ $Date$ + */ +public class StatefulSecurityPermissionsTest extends TestCase { + + @AfterClass + public static void afterClass() throws Exception { + OpenEJB.destroy(); + } + + public void test() throws Exception { + System.setProperty(javax.naming.Context.INITIAL_CONTEXT_FACTORY, org.apache.openejb.core.LocalInitialContextFactory.class.getName()); + + final Assembler assembler = new Assembler(); + final ConfigurationFactory config = new ConfigurationFactory(); + + assembler.createProxyFactory(config.configureService(ProxyFactoryInfo.class)); + assembler.createTransactionManager(config.configureService(TransactionServiceInfo.class)); + final SecurityServiceInfo securityServiceInfo = config.configureService(SecurityServiceInfo.class); + securityServiceInfo.className = TestSecurityService.class.getName(); + assembler.createSecurityService(securityServiceInfo); + + final TestSecurityService securityService = (TestSecurityService) SystemInstance.get().getComponent(SecurityService.class); + + securityService.login("foo", "Jazz", "Rock", "Reggae", "HipHop"); + + final EjbJar ejbJar = new EjbJar(); + ejbJar.addEnterpriseBean(new StatefulBean(Color.class)); + final List<MethodPermission> permissions = ejbJar.getAssemblyDescriptor().getMethodPermission(); + permissions.add(new MethodPermission("*", "Color", "*", "Foo")); + permissions.add(new MethodPermission("*", "Color", "create").setUnchecked()); + permissions.add(new MethodPermission("*", "Color", "ejbCreate").setUnchecked()); + + final EjbJarInfo ejbJarInfo = config.configureApplication(ejbJar); + assembler.createApplication(ejbJarInfo); + + final InitialContext context = new InitialContext(); + + { + final ColorLocal color = (ColorLocal) context.lookup("ColorLocal"); + + assertEquals("Jazz", color.color()); + try { + color.color((Object) null); + } catch (final EJBAccessException e) { + assertEquals("Excluded", actual.get()); + } + assertEquals("Rock", color.color((String) null)); + assertEquals("Unchecked", color.color((Boolean) null)); + assertEquals("Reggae", color.color((Integer) null)); + } + + } + + public static ThreadLocal<String> expected = new ThreadLocal<String>(); + + @LocalHome(ColorEjbLocalHome.class) + @RemoteHome(ColorEjbHome.class) + public static class Color implements ColorLocal, ColorRemote { + + protected String attribute() { + return actual.get(); + } + + @Init + public void ejbCreate(final String s) { + assertEquals(s, attribute()); + } + + @Remove + public void ejbRemove() { + assertEquals(expected.get(), attribute()); + } + + + @RolesAllowed({"Jazz"}) + public String color() { + return attribute(); + } + + @DenyAll + public String color(final Object o) { + return attribute(); + } + + @RolesAllowed({"Rock"}) + public String color(final String s) { + return attribute(); + } + + @PermitAll + public String color(final Boolean b) { + return attribute(); + } + + @RolesAllowed({"Reggae"}) + public String color(final Integer i) { + return attribute(); + } + + + } + + @Local + public static interface ColorLocal { + public String color(); + + public String color(Object o); + + public String color(String s); + + public String color(Boolean b); + + public String color(Integer i); + } + + @Remote + public static interface ColorRemote { + public String color(); + + public String color(Object o); + + public String color(String s); + + public String color(Boolean b); + + public String color(Integer i); + } + + public static interface ColorEjbHome extends EJBHome { + ColorEjbObject create(String s) throws CreateException, RemoteException; + } + + public static interface ColorEjbObject extends EJBObject { + public String color() throws RemoteException; + + public String color(Object o) throws RemoteException; + + public String color(String s) throws RemoteException; + + public String color(Boolean b) throws RemoteException; + + public String color(Integer i) throws RemoteException; + } + + public static interface ColorEjbLocalHome extends EJBLocalHome { + ColorEjbLocalObject create(String s) throws CreateException; + } + + public static interface ColorEjbLocalObject extends EJBLocalObject { + public String color(); + + public String color(Object o); + + public String color(String s); + + public String color(Boolean b); + + public String color(Integer i); + } + + + private static final ThreadLocal<String> actual = new ThreadLocal<String>(); + + public static class TestSecurityService extends AbstractSecurityService { + + public TestSecurityService() { + super(TestJaccProvider.class.getName()); + } + + public UUID login(final String securityRealm, final String user, final String pass) throws LoginException { + return null; + } + + @Override + public UUID login(final String securityRealm, final String user, final String pass, final long accessTimeout) throws LoginException { + return null; + } + + public void login(final String user, final String... roles) throws LoginException { + final Set<Principal> set = new HashSet<Principal>(); + set.add(new UserPrincipal(user)); + for (final String role : roles) { + set.add(new GroupPrincipal(role)); + } + final Subject subject = new Subject(true, set, Collections.EMPTY_SET, Collections.EMPTY_SET); + final UUID uuid = registerSubject(subject); + associate(uuid); + } + + public void logout() { + this.disassociate(); + } + + public static class TestJaccProvider extends BasicJaccProvider { + protected BasicPolicyConfiguration createPolicyConfiguration(final String contextID) { + return new TestPolicy(contextID); + } + + public static class TestPolicy extends BasicPolicyConfiguration { + + TestPolicy(final String contextID) { + super(contextID); + } + + public boolean implies(final ProtectionDomain domain, final Permission permission) { + + if (excluded != null && excluded.implies(permission)) { + actual.set("Excluded"); + return false; + } + + if (unchecked != null && unchecked.implies(permission)) { + actual.set("Unchecked"); + return true; + } + + final Principal[] principals = domain.getPrincipals(); + if (principals.length == 0) { + return false; + } + + final RoleResolver roleResolver = SystemInstance.get().getComponent(RoleResolver.class); + final Set<String> roles = roleResolver.getLogicalRoles(principals, rolePermissionsMap.keySet()); + + for (final String role : roles) { + final PermissionCollection permissions = rolePermissionsMap.get(role); + + if (permissions != null && permissions.implies(permission)) { + actual.set(role); + return true; + } + } + + actual.set("Denied"); + return false; + } + } + } + } +} http://git-wip-us.apache.org/repos/asf/tomee/blob/5c4316b5/server/openejb-client/src/main/java/org/apache/openejb/client/AuthenticationRequest.java ---------------------------------------------------------------------- diff --git a/server/openejb-client/src/main/java/org/apache/openejb/client/AuthenticationRequest.java b/server/openejb-client/src/main/java/org/apache/openejb/client/AuthenticationRequest.java index f2defdd..f9b0bd7 100644 --- a/server/openejb-client/src/main/java/org/apache/openejb/client/AuthenticationRequest.java +++ b/server/openejb-client/src/main/java/org/apache/openejb/client/AuthenticationRequest.java @@ -1,134 +1,135 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.openejb.client; - -import java.io.IOException; -import java.io.ObjectInput; -import java.io.ObjectOutput; - -public class AuthenticationRequest implements Request { - - /** - * Never change this, use #metaData for version - */ - private static final long serialVersionUID = 7009531340198948330L; - - private transient String realm; - private transient String username; - private transient String credentials; - private transient long timeout; - private transient ProtocolMetaData metaData; - private transient boolean logout = false; - - public AuthenticationRequest() { - } - - public AuthenticationRequest(final String principal, final String credentials) { - this(null, principal, credentials, 0); - } - - public AuthenticationRequest(final String principal, final String credentials, final long timeout) { - this(null, principal, credentials, timeout); - } - - public AuthenticationRequest(final String securityRealm, final String username, final String password) { - this(securityRealm, username, password, 0); - } - - public AuthenticationRequest(final String realm, final String principal, final String credentials, final long timeout) { - this.realm = realm; - this.username = principal; - this.credentials = credentials; - this.timeout = timeout; - } - - @Override - public void setMetaData(final ProtocolMetaData metaData) { - this.metaData = metaData; - } - - @Override - public RequestType getRequestType() { - return RequestType.AUTH_REQUEST; - } - - public String getRealm() { - return realm; - } - - public String getUsername() { - return username; - } - - public String getCredentials() { - return credentials; - } - - public long getTimeout() { - return timeout; - } - - public boolean isLogout() { - return logout; - } - - public void setLogout(final boolean logout) { - this.logout = logout; - } - - /** - * Changes to this method must observe the optional {@link #metaData} version - */ - @Override - public void readExternal(final ObjectInput in) throws IOException, ClassNotFoundException { - in.readByte(); // Not used @see #metaData - - realm = (String) in.readObject(); - username = (String) in.readObject(); - credentials = (String) in.readObject(); - - if (null == metaData || metaData.isAtLeast(4, 7)) { - timeout = in.readLong(); - logout = in.readBoolean(); - } - } - - /** - * Changes to this method must observe the optional {@link #metaData} version - */ - @Override - public void writeExternal(final ObjectOutput out) throws IOException { - // Not used, but must be written @see #metaData - out.writeByte(1); - - out.writeObject(realm); - out.writeObject(username); - out.writeObject(credentials); - out.writeLong(timeout); - out.writeBoolean(logout); - } - - public String toString() { - final StringBuilder sb = new StringBuilder(50); - sb.append(null != realm ? realm : "Unknown realm").append(':'); - sb.append(null != username ? username : "Unknown user").append(':'); - sb.append(null != credentials ? credentials : "Unknown credentials").append(':'); - sb.append(timeout); - return sb.toString(); - } -} - +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.openejb.client; + +import java.io.IOException; +import java.io.ObjectInput; +import java.io.ObjectOutput; + +public class AuthenticationRequest implements Request { + + /** + * Never change this, use #metaData for version + */ + private static final long serialVersionUID = 7009531340198948330L; + + private transient String realm; + private transient String username; + private transient String credentials; + private transient long timeout; + private transient ProtocolMetaData metaData; + private transient Object logoutIdentity = null; + + public AuthenticationRequest() { + } + + public AuthenticationRequest(final String principal, final String credentials) { + this(null, principal, credentials, 0); + } + + public AuthenticationRequest(final String principal, final String credentials, final long timeout) { + this(null, principal, credentials, timeout); + } + + public AuthenticationRequest(final String securityRealm, final String username, final String password) { + this(securityRealm, username, password, 0); + } + + public AuthenticationRequest(final String realm, final String principal, final String credentials, final long timeout) { + this.realm = realm; + this.username = principal; + this.credentials = credentials; + this.timeout = timeout; + } + + @Override + public void setMetaData(final ProtocolMetaData metaData) { + this.metaData = metaData; + } + + @Override + public RequestType getRequestType() { + return RequestType.AUTH_REQUEST; + } + + public String getRealm() { + return realm; + } + + public String getUsername() { + return username; + } + + public String getCredentials() { + return credentials; + } + + public long getTimeout() { + return timeout; + } + + public Object getLogoutIdentity() { + return logoutIdentity; + } + + public void setLogoutIdentity(final Object logoutIdentity) { + this.logoutIdentity = logoutIdentity; + } + + /** + * Changes to this method must observe the optional {@link #metaData} version + */ + @Override + public void readExternal(final ObjectInput in) throws IOException, ClassNotFoundException { + in.readByte(); // Not used @see #metaData + + realm = (String) in.readObject(); + username = (String) in.readObject(); + credentials = (String) in.readObject(); + + if (null == metaData || metaData.isAtLeast(4, 7)) { + timeout = in.readLong(); + logoutIdentity = in.readObject(); + } + } + + /** + * Changes to this method must observe the optional {@link #metaData} version + */ + @Override + public void writeExternal(final ObjectOutput out) throws IOException { + // Not used, but must be written @see #metaData + out.writeByte(1); + + out.writeObject(realm); + out.writeObject(username); + out.writeObject(credentials); + out.writeLong(timeout); + out.writeObject(logoutIdentity); + } + + public String toString() { + final StringBuilder sb = new StringBuilder(50); + sb.append(null != realm ? realm : "Undefined realm").append(':'); + sb.append(null != username ? username : "Undefined user").append(':'); + sb.append(null != credentials ? credentials : "Undefined credentials").append(':'); + sb.append(null != logoutIdentity ? logoutIdentity : "Undefined logoutIdentity").append(':'); + sb.append(timeout); + return sb.toString(); + } +} +