All Downloads are FREE. Search and download functionalities are using the official Maven repository.
Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
org.apache.openejb.core.security.AbstractSecurityService Maven / Gradle / Ivy
/*
* 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.spi.SecurityService;
import org.apache.openejb.spi.CallerPrincipal;
import org.apache.openejb.core.ThreadContextListener;
import org.apache.openejb.core.ThreadContext;
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.InterfaceType;
import org.apache.openejb.BeanContext;
import org.apache.openejb.loader.SystemInstance;
import javax.security.auth.Subject;
import javax.security.auth.login.LoginException;
import javax.security.jacc.PolicyContext;
import javax.security.jacc.EJBMethodPermission;
import javax.security.jacc.PolicyConfigurationFactory;
import java.io.Serializable;
import java.security.AccessControlContext;
import java.security.PrivilegedAction;
import java.security.AccessController;
import java.security.Principal;
import java.security.AccessControlException;
import java.security.Permission;
import java.security.Policy;
import java.util.UUID;
import java.util.List;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Collections;
import java.util.Properties;
import java.util.Set;
import java.util.HashSet;
import java.util.Map;
import java.util.LinkedHashSet;
import java.util.concurrent.ConcurrentHashMap;
import java.lang.reflect.Method;
/**
* 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, ThreadContextListener, BasicPolicyConfiguration.RoleResolver {
static private final Map identities = new ConcurrentHashMap();
static protected final ThreadLocal clientIdentity = new ThreadLocal();
protected String defaultUser = "guest";
private String realmName = "PropertiesLogin";
protected Subject defaultSubject;
protected SecurityContext defaultContext;
public AbstractSecurityService() {
this(BasicJaccProvider.class.getName());
}
public AbstractSecurityService(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(String realmName) {
this.realmName = realmName;
}
/**
* @return the defaultUser
*/
public String getDefaultUser() {
return defaultUser;
}
/**
* @param defaultUser the defaultUser to set
*/
public void setDefaultUser(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);
defaultContext = new SecurityContext(defaultSubject);
}
public void init(Properties props) throws Exception {
}
public UUID login(String username, String password) throws LoginException {
return login(realmName, username, password);
}
public Set getLogicalRoles(Principal[] principals, Set logicalRoles) {
LinkedHashSet roles = new LinkedHashSet(principals.length);
for (Principal principal : principals) {
String name = principal.getName();
if (logicalRoles.contains(name)) {
roles.add(name);
}
}
return roles;
}
public void contextEntered(ThreadContext oldContext, ThreadContext newContext) {
String moduleID = newContext.getBeanContext().getModuleID();
PolicyContext.setContextID(moduleID);
SecurityContext securityContext = (oldContext != null) ? oldContext.get(SecurityContext.class) : null;
BeanContext callingBeanContext = (oldContext != null)? oldContext.getBeanContext(): null;
Subject runAsSubject = getRunAsSubject(callingBeanContext);
if (runAsSubject != null) {
securityContext = new SecurityContext(runAsSubject);
} else if (securityContext == null) {
Identity identity = clientIdentity.get();
if (identity != null){
securityContext = new SecurityContext(identity.subject);
} else {
securityContext = defaultContext;
}
}
newContext.set(SecurityContext.class, securityContext);
}
protected Subject getRunAsSubject(BeanContext callingBeanContext) {
if (callingBeanContext == null) return null;
String runAsRole = callingBeanContext.getRunAs();
Subject runAs = createRunAsSubject(runAsRole);
return runAs;
}
protected Subject createRunAsSubject(String runAsRole) {
return createSubject(runAsRole);
}
public void contextExited(ThreadContext exitedContext, ThreadContext reenteredContext) {
if (reenteredContext == null) {
PolicyContext.setContextID(null);
} else {
PolicyContext.setContextID(reenteredContext.getBeanContext().getModuleID());
}
}
protected UUID registerSubject(Subject subject) {
Identity identity = new Identity(subject);
UUID token = identity.getToken();
identities.put(token, identity);
return token;
}
public void logout(UUID securityIdentity) throws LoginException {
Identity identity = identities.get(securityIdentity);
if (identity == null) throw new LoginException("Identity is not currently logged in: " + securityIdentity);
identities.remove(securityIdentity);
}
protected void unregisterSubject(Object securityIdentity) {
identities.remove(securityIdentity);
}
public void associate(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
Identity identity = identities.get(securityIdentity);
if (identity == null) throw new LoginException("Identity is not currently logged in: " + securityIdentity);
clientIdentity.set(identity);
}
public UUID disassociate() {
try {
Identity identity = clientIdentity.get();
return (identity == null)? null: identity.getToken();
} finally {
clientIdentity.remove();
}
}
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);
final Set grps = securityContext.subject.getPrincipals(Group.class);
for (Group grp : grps) {
if(grp.getName().equals(role)) {
return true;
}
}
final Set grpsp = securityContext.subject.getPrincipals(GroupPrincipal.class);
for (GroupPrincipal grp : grpsp) {
if(grp.getName().equals(role)) {
return true;
}
}
return false;
}
public Principal getCallerPrincipal() {
ThreadContext threadContext = ThreadContext.getThreadContext();
SecurityContext securityContext = threadContext.get(SecurityContext.class);
Set principals = securityContext.subject.getPrincipals();
if (!principals.isEmpty()) {
for (Principal principal : principals) {
if (principal.getClass().isAnnotationPresent(CallerPrincipal.class)) {
return principal;
}
}
return principals.iterator().next();
}
return null;
}
public boolean isCallerAuthorized(Method method, InterfaceType type) {
ThreadContext threadContext = ThreadContext.getThreadContext();
SecurityContext securityContext = threadContext.get(SecurityContext.class);
try {
BeanContext beanContext = threadContext.getBeanContext();
String ejbName = beanContext.getEjbName();
String name = (type == null)? null: type.getSpecName();
if ("LocalBean".equals(name) || "LocalBeanHome".equals(name)) {
name = null;
}
Permission permission = new EJBMethodPermission(ejbName, name, method);
if (permission != null) securityContext.acc.checkPermission(permission);
} catch (AccessControlException e) {
return false;
}
return true;
}
protected static void installJacc() {
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());
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 (Exception e) {
throw new IllegalStateException("Could not install JACC Policy Configuration Factory: " + System.getProperty(providerKey), e);
} finally {
Thread.currentThread().setContextClassLoader(contextClassLoader);
}
String policyProvider = System.getProperty("javax.security.jacc.policy.provider", JaccProvider.Policy.class.getName());
try {
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
Class policyClass = Class.forName(policyProvider, true, classLoader);
Policy policy = (Policy) policyClass.newInstance();
policy.refresh();
Policy.setPolicy(policy);
} catch (Exception e) {
throw new IllegalStateException("Could not install JACC Policy Provider: "+policyProvider, e);
}
}
protected Subject createSubject(String name) {
if (name == null) return null;
User user = new User(name);
Group group = new Group(name);
group.addMember(user);
HashSet principals = new HashSet();
principals.add(user);
principals.add(group);
return new Subject(true, principals, new HashSet(), new HashSet());
}
protected final static class SecurityContext {
private final Subject subject;
private final AccessControlContext acc;
public SecurityContext(Subject subject) {
this.subject = subject;
this.acc = (AccessControlContext) Subject.doAsPrivileged(subject, new PrivilegedAction() {
public Object run() {
return AccessController.getContext();
}
}, null);
}
}
protected static class Identity implements Serializable {
private final Subject subject;
private final UUID token;
public Identity(Subject subject) {
this.subject = subject;
this.token = UUID.randomUUID();
}
public Identity(Subject subject, UUID token) {
this.subject = subject;
this.token = token;
}
public Subject getSubject() {
return subject;
}
public UUID getToken() {
return token;
}
}
public static class Group implements java.security.acl.Group {
private final List members = new ArrayList();
private final String name;
public Group(String name) {
this.name = name;
}
public boolean addMember(Principal user) {
return members.add(user);
}
public boolean removeMember(Principal user) {
return members.remove(user);
}
public boolean isMember(Principal member) {
return members.contains(member);
}
public Enumeration members() {
return Collections.enumeration(members);
}
public String getName() {
return name;
}
}
public static class User implements Principal {
private final String name;
public User(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
}