/**
* Copyright (c) 2000-present Liferay, Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 2.1 of the License, or (at your option)
* any later version.
*
* This library is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*/
package com.liferay.portal.security.pacl;
import com.liferay.portal.bean.BeanLocatorImpl;
import com.liferay.portal.dao.jdbc.DataSourceFactoryImpl;
import com.liferay.portal.dao.orm.hibernate.DynamicQueryFactoryImpl;
import com.liferay.portal.deploy.hot.HotDeployImpl;
import com.liferay.portal.kernel.bean.BeanLocator;
import com.liferay.portal.kernel.bean.PortalBeanLocatorUtil;
import com.liferay.portal.kernel.concurrent.ConcurrentIdentityHashMap;
import com.liferay.portal.kernel.concurrent.ConcurrentReferenceKeyHashMap;
import com.liferay.portal.kernel.concurrent.ConcurrentReferenceValueHashMap;
import com.liferay.portal.kernel.dao.jdbc.DataAccess;
import com.liferay.portal.kernel.jndi.JNDIUtil;
import com.liferay.portal.kernel.log.Log;
import com.liferay.portal.kernel.log.LogFactoryUtil;
import com.liferay.portal.kernel.memory.EqualityWeakReference;
import com.liferay.portal.kernel.memory.FinalizeManager;
import com.liferay.portal.kernel.portlet.PortletClassLoaderUtil;
import com.liferay.portal.kernel.security.pacl.PACLConstants;
import com.liferay.portal.kernel.security.pacl.permission.PortalFilePermission;
import com.liferay.portal.kernel.security.pacl.permission.PortalHookPermission;
import com.liferay.portal.kernel.security.pacl.permission.PortalMessageBusPermission;
import com.liferay.portal.kernel.security.pacl.permission.PortalRuntimePermission;
import com.liferay.portal.kernel.security.pacl.permission.PortalServicePermission;
import com.liferay.portal.kernel.security.pacl.permission.PortalSocketPermission;
import com.liferay.portal.kernel.url.URLContainer;
import com.liferay.portal.kernel.util.AutoResetThreadLocal;
import com.liferay.portal.kernel.util.CentralizedThreadLocal;
import com.liferay.portal.kernel.util.ClassLoaderUtil;
import com.liferay.portal.kernel.util.InfrastructureUtil;
import com.liferay.portal.kernel.util.JavaDetector;
import com.liferay.portal.kernel.util.PreloadClassLoader;
import com.liferay.portal.kernel.util.PropsKeys;
import com.liferay.portal.kernel.util.PropsUtil;
import com.liferay.portal.kernel.util.ProxyUtil;
import com.liferay.portal.kernel.util.ReferenceEntry;
import com.liferay.portal.kernel.util.ReferenceRegistry;
import com.liferay.portal.kernel.util.ReflectionUtil;
import com.liferay.portal.kernel.util.ServerDetector;
import com.liferay.portal.kernel.util.Validator;
import com.liferay.portal.security.lang.DoPrivilegedBean;
import com.liferay.portal.security.lang.DoPrivilegedFactory;
import com.liferay.portal.security.lang.DoPrivilegedHandler;
import com.liferay.portal.security.lang.DoPrivilegedUtil;
import com.liferay.portal.security.lang.PortalSecurityManager;
import com.liferay.portal.security.pacl.dao.jdbc.PACLConnectionHandler;
import com.liferay.portal.security.pacl.dao.jdbc.PACLDataSource;
import com.liferay.portal.security.pacl.dao.jdbc.PACLStatementHandler;
import com.liferay.portal.security.pacl.jndi.PACLContext;
import com.liferay.portal.security.pacl.jndi.PACLInitialContextFactory;
import com.liferay.portal.security.pacl.jndi.PACLInitialContextFactoryBuilder;
import com.liferay.portal.security.pacl.jndi.SchemeAwareContextWrapper;
import com.liferay.portal.security.pacl.servlet.PACLRequestDispatcherWrapper;
import com.liferay.portal.service.impl.ServiceComponentLocalServiceImpl;
import com.liferay.portal.service.impl.ServiceComponentLocalServiceImpl.DoUpgradeDBPrivilegedExceptionAction;
import com.liferay.portal.servlet.DirectRequestDispatcherFactoryImpl;
import com.liferay.portal.spring.aop.ServiceBeanAopProxy;
import com.liferay.portal.spring.bean.BeanReferenceAnnotationBeanPostProcessor;
import com.liferay.portal.spring.bean.BeanReferenceRefreshUtil;
import com.liferay.portal.spring.bean.BeanReferenceRefreshUtil.PACL;
import com.liferay.portal.spring.context.PortletApplicationContext;
import com.liferay.portal.template.BaseTemplateManager;
import com.liferay.portal.template.TemplateContextHelper;
import com.liferay.portal.template.TemplateControlContext;
import com.liferay.portal.util.PropsValues;
import com.liferay.portlet.PortletRequestImpl;
import com.liferay.portlet.PortletResponseImpl;
import com.liferay.portlet.PortletURLImpl;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodHandles.Lookup;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Member;
import java.lang.reflect.Method;
import java.lang.reflect.ReflectPermission;
import java.net.SocketPermission;
import java.security.AccessControlContext;
import java.security.AccessController;
import java.security.Permission;
import java.security.Policy;
import java.security.PrivilegedAction;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import java.security.ProtectionDomain;
import java.util.HashMap;
import java.util.IdentityHashMap;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import javax.ccpp.Profile;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.naming.spi.InitialContextFactoryBuilder;
import javax.naming.spi.NamingManager;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletContext;
import javax.sql.DataSource;
import org.eclipse.osgi.internal.permadmin.EquinoxSecurityManager;
import org.osgi.framework.BundleReference;
import org.springframework.aop.framework.AdvisedSupport;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
/**
* This is the portal's implementation of a security manager. The goal is to
* protect portal resources from plugins and prevent security issues by forcing
* plugin developers to openly declare their requirements. Where a
* SecurityManager exists, we set that as the parent and delegate to it as a
* fallback. This class will not delegate checks to super when there is no
* parent so as to avoid forcing the need for a default policy.
*
* @author Brian Wing Shun Chan
* @author Raymond Augé
* @author Zsolt Berentey
*/
public class PortalSecurityManagerImpl
extends EquinoxSecurityManager implements PortalSecurityManager {
public PortalSecurityManagerImpl()
throws IllegalAccessException, NoSuchMethodException,
SecurityException {
_originalSecurityManager = System.getSecurityManager();
Lookup lookup = MethodHandles.lookup();
Class<?> clazz = getClass();
clazz = clazz.getSuperclass();
Method method = clazz.getDeclaredMethod(
"internalCheckPermission", Permission.class, Object.class);
method.setAccessible(true);
MethodHandle methodHandle = lookup.unreflect(method);
_checkPermissionMethodHandle = methodHandle.bindTo(this);
initClasses();
PortalPolicy portalPolicy = null;
try {
Policy policy = null;
if (_originalSecurityManager != null) {
policy = Policy.getPolicy();
}
portalPolicy = new PortalPolicy(policy);
Policy.setPolicy(portalPolicy);
portalPolicy.refresh();
}
catch (Exception e) {
if (_log.isInfoEnabled()) {
_log.info(
"Unable to override the original Java security policy " +
"because sufficient privileges are not granted to " +
"Liferay. PACL is not enabled.");
}
if (_log.isWarnEnabled()) {
_log.warn(e, e);
}
}
_portalPolicy = portalPolicy;
try {
initInitialContextFactoryBuilder();
}
catch (Exception e) {
if (_log.isInfoEnabled()) {
_log.info(
"Unable to override the initial context factory builder " +
"because one already exists. JNDI security is not " +
"enabled.");
}
if (_log.isWarnEnabled()) {
_log.warn(e, e);
}
}
try {
initPACLImpls();
}
catch (Exception e) {
if (_log.isInfoEnabled()) {
_log.info(
"Unable to initialize portal runtime permissions. Some " +
"portal runtime security is not enabled.");
}
if (_log.isWarnEnabled()) {
_log.warn(e, e);
}
}
if (ServerDetector.isWebLogic()) {
addWebLogicHook();
}
if (ServerDetector.isWebSphere()) {
addWebSphereHook();
}
}
/**
* @deprecated As of 1.0.0
*/
@Deprecated
@Override
public void checkMemberAccess(Class<?> clazz, int accessibility) {
if (clazz == null) {
throw new NullPointerException("Class is null");
}
ClassLoader clazzClassLoader = ClassLoaderUtil.getClassLoader(clazz);
if ((accessibility == Member.PUBLIC) ||
((clazzClassLoader != null) &&
!BundleReference.class.isInstance(clazzClassLoader) &&
PACLUtil.hasSameOrigin(clazz))) {
_checkMemberAccessClassLoader.set(clazzClassLoader);
return;
}
Class<?>[] stack = getClassContext();
// Stack depth of 4 should be the caller of one of the methods in
// java.lang.Class that invoked the checkMember access. The stack should
// look like:
// [3] someCaller
// [2] java.lang.Class.someReflectionAPI
// [1] java.lang.Class.checkMemberAccess
// [0] SecurityManager.checkMemberAccess
if ((stack.length < 4) ||
(ClassLoaderUtil.getClassLoader(stack[3]) != clazzClassLoader)) {
_checkMemberAccessClassLoader.set(null);
checkPermission(_checkMemberAccessPermission);
}
else {
_checkMemberAccessClassLoader.set(clazzClassLoader);
}
}
@Override
public void checkPermission(Permission permission) {
String name = permission.getName();
if ((permission instanceof ReflectPermission) &&
name.equals("suppressAccessChecks") &&
(_checkMemberAccessClassLoader.get() != null)) {
// The "suppressAccessChecks" permission is particularly difficult
// to handle because the Java API does not have a mechanism to get
// the class on which the accessibility is being suppressed. This
// makes it difficult to differentiate between code changing its own
// accessibility (allowed) from accessibility changes on foreign
// code (not allowed). However, there is a common programming
// pattern we can take advantage of to short circuit the problem.
// T t = clazz.getDeclared*(..);
// t.setAccessible(true);
// Call getDeclared* and immediately change the accessibility of it.
// The getDeclared* results in a call to
// SecurityManager#checkMemberAccess(Class, int). In the case where
// the target class and the caller class are from the same class
// loader, the checking is short circuited with a successful result.
// If this short circuit happens in our implementation, we will
// store the class loader of the target class, and on the very next
// permission check, if the check is for "suppressAccessChecks" and
// the classLoader of the caller is the same as the stored class
// loader from the previous check, we will also allow the check to
// succeed. In all cases, the thread local is purged to avoid later
// erroneous successes.
Class<?>[] stack = getClassContext();
// [2] someCaller
// [1] java.lang.reflect.AccessibleObject
// [0] SecurityManager.checkMemberAccess
if (_checkMemberAccessClassLoader.get() ==
ClassLoaderUtil.getClassLoader(stack[2])) {
return;
}
}
AccessController.doPrivileged(
new PermissionAction(
_checkPermissionMethodHandle, permission,
getSecurityContext()));
}
@Override
public void destroy() {
synchronized (_originalSecurityManager) {
Policy.setPolicy(_portalPolicy.getOriginalPolicy());
System.setSecurityManager(_originalSecurityManager);
}
}
@Override
public Policy getPolicy() {
return _portalPolicy;
}
protected void addWebLogicHook() {
final SecurityManager securityManager = this;
try {
ScheduledExecutorService scheduledExecutor =
Executors.newSingleThreadScheduledExecutor();
Runnable runnable = new Runnable() {
@Override
public void run() {
if (securityManager != System.getSecurityManager()) {
_originalSecurityManager = System.getSecurityManager();
System.setSecurityManager(securityManager);
}
}
};
scheduledExecutor.scheduleAtFixedRate(
runnable, 100, 100, TimeUnit.MILLISECONDS);
}
catch (Exception e) {
_log.error(e, e);
}
}
protected void addWebSphereHook() {
try {
Class.forName("com.liferay.support.websphere.DynamicPolicyHelper");
}
catch (Exception e) {
_log.error(e, e);
}
}
protected void initClass(Class<?> clazz) {
// Do not remove this seemingly useless declaration. We need the current
// class loader to load all the inner classes.
Class<?>[] declaredClasses = clazz.getDeclaredClasses();
int declaredClassesLength = declaredClasses.length;
if (_log.isDebugEnabled()) {
_log.debug(
"Loading " + clazz.getName() + " and " + declaredClassesLength +
" inner classes");
}
}
@SuppressWarnings("deprecation")
protected void initClasses() {
// Load dependent classes to prevent ClassCircularityError
// This class' own inner classes
initClass(getClass());
// Other classes
initClass(ActivePACLPolicy.class);
initClass(BaseTemplateManager.class);
initClass(CentralizedThreadLocal.class);
initClass(ConcurrentIdentityHashMap.class);
initClass(ConcurrentReferenceKeyHashMap.class);
initClass(ConcurrentReferenceValueHashMap.class);
initClass(DoPrivilegedBean.class);
initClass(DoPrivilegedFactory.class);
initClass(DoPrivilegedHandler.class);
initClass(DynamicQueryFactoryImpl.class);
initClass(EqualityWeakReference.class);
initClass(FinalizeManager.class);
initClass(GeneratingPACLPolicy.class);
initClass(InactivePACLPolicy.class);
initClass(LenientPermissionCollection.class);
initClass(PACLAdvice.class);
initClass(PACLBeanHandler.class);
initClass(PACLClassLoaderUtil.class);
initClass(PACLClassUtil.class);
initClass(PACLConnectionHandler.class);
initClass(PACLContext.class);
initClass(PACLDataSource.class);
initClass(PACLInvocationHandler.class);
initClass(PACLInitialContextFactory.class);
initClass(PACLInitialContextFactoryBuilder.class);
initClass(PACLPolicyManager.class);
initClass(PACLPolicyThreadLocal.class);
initClass(PACLRequestDispatcherWrapper.class);
initClass(PACLStatementHandler.class);
initClass(PACLUtil.class);
initClass(PortalHookPermission.class);
initClass(PortalMessageBusPermission.class);
initClass(PortalPermissionCollection.class);
initClass(PortalRuntimePermission.class);
initClass(PortalServicePermission.class);
initClass(PortalPolicy.class);
initClass(PortletRequestImpl.class);
initClass(PortletResponseImpl.class);
initClass(PortletURLImpl.class);
initClass(Profile.class);
initClass(Reflection.class);
initClass(SchemeAwareContextWrapper.class);
initClass(TemplateContextHelper.class);
initClass(URLWrapper.class);
initClass(
com.liferay.portal.kernel.util.WeakValueConcurrentHashMap.class);
}
protected void initInitialContextFactoryBuilder() throws Exception {
if (!NamingManager.hasInitialContextFactoryBuilder()) {
PACLInitialContextFactoryBuilder paclInitialContextFactoryBuilder =
new PACLInitialContextFactoryBuilder();
if (_log.isInfoEnabled()) {
_log.info("Overriding the initial context factory builder");
}
NamingManager.setInitialContextFactoryBuilder(
paclInitialContextFactoryBuilder);
}
Class<?> clazz = NamingManager.class;
String fieldName = "initctx_factory_builder";
if (JavaDetector.isIBM()) {
fieldName = "icfb";
}
Field field = clazz.getDeclaredField(fieldName);
field.setAccessible(true);
InitialContextFactoryBuilder initialContextFactoryBuilder =
(InitialContextFactoryBuilder)field.get(null);
if (initialContextFactoryBuilder instanceof
PACLInitialContextFactoryBuilder) {
return;
}
PACLInitialContextFactoryBuilder paclInitialContextFactoryBuilder =
new PACLInitialContextFactoryBuilder();
paclInitialContextFactoryBuilder.setInitialContextFactoryBuilder(
initialContextFactoryBuilder);
field.set(null, paclInitialContextFactoryBuilder);
if (_log.isInfoEnabled()) {
_log.info(
"Overriding the initial context factory builder using " +
"reflection");
}
}
protected void initPACLImpl(Class<?> clazz, Object pacl) throws Exception {
Field field = ReflectionUtil.getDeclaredField(clazz, "_pacl");
synchronized (field) {
field.setAccessible(true);
field.set(null, pacl);
}
}
protected void initPACLImpls() throws Exception {
initPACLImpl(BeanLocatorImpl.class, new DoBeanLocatorImplPACL());
initPACLImpl(
BeanReferenceRefreshUtil.class,
new DoBeanReferenceRefreshUtilPACL());
initPACLImpl(ClassLoaderUtil.class, new DoClassLoaderUtilPACL());
initPACLImpl(DataAccess.class, new DoDataAccessPACL());
initPACLImpl(
DataSourceFactoryImpl.class, new DoDataSourceFactoryImplPACL());
initPACLImpl(
DirectRequestDispatcherFactoryImpl.class,
new DoDirectRequestDispatcherFactoryImplPACL());
initPACLImpl(DoPrivilegedUtil.class, new DoDoPrivilegedPACL());
initPACLImpl(HotDeployImpl.class, new DoHotDeployImplPACL());
initPACLImpl(
PortalBeanLocatorUtil.class, new DoPortalBeanLocatorUtilPACL());
initPACLImpl(
PortalFilePermission.class, new DoPortalFilePermissionPACL());
initPACLImpl(
PortalHookPermission.class, new DoPortalHookPermissionPACL());
initPACLImpl(
PortalMessageBusPermission.class,
new DoPortalMessageBusPermissionPACL());
initPACLImpl(
PortalRuntimePermission.class, new DoPortalRuntimePermissionPACL());
initPACLImpl(
PortalServicePermission.class, new DoPortalServicePermissionPACL());
initPACLImpl(
PortalSocketPermission.class, new DoPortalSocketPermissionPACL());
initPACLImpl(
PortletApplicationContext.class,
new DoPortletApplicationContextPACL());
initPACLImpl(ReferenceRegistry.class, new DoReferenceRegistryPACL());
initPACLImpl(
ServiceBeanAopProxy.class, new DoServiceBeanAopProxyPACL());
initPACLImpl(
ServiceComponentLocalServiceImpl.class,
new DoServiceComponentLocalServiceImplPACL());
initPACLImpl(
TemplateContextHelper.class, new DoTemplateContextHelperPACL());
}
private static final Log _log = LogFactoryUtil.getLog(
PortalSecurityManagerImpl.class.getName());
private static final ThreadLocal<ClassLoader>
_checkMemberAccessClassLoader = new AutoResetThreadLocal<>(
PortalSecurityManagerImpl.class +
"._checkMembersAccessClassLoader");
private static final RuntimePermission _checkMemberAccessPermission =
new RuntimePermission("accessDeclaredMembers");
private final MethodHandle _checkPermissionMethodHandle;
private SecurityManager _originalSecurityManager;
private final PortalPolicy _portalPolicy;
private static class DoBeanLocatorImplPACL implements BeanLocatorImpl.PACL {
@Override
public Object getBean(final Object bean, ClassLoader classLoader) {
Class<?> beanClass = bean.getClass();
if (ProxyUtil.isProxyClass(beanClass) &&
(ProxyUtil.getInvocationHandler(bean) instanceof
PACLInvocationHandler)) {
return bean;
}
Class<?>[] interfaces = ReflectionUtil.getInterfaces(
bean, classLoader);
if (interfaces.length == 0) {
return bean;
}
if (classLoader == ClassLoaderUtil.getPortalClassLoader()) {
Class<?> callerClass = Reflection.getCallerClass(5);
ClassLoader callerClassLoader = ClassLoaderUtil.getClassLoader(
callerClass);
if (callerClassLoader == classLoader) {
String callerClassName = callerClass.getName();
if (!callerClassName.equals(
BeanReferenceAnnotationBeanPostProcessor.class.
getName())) {
return bean;
}
}
}
InvocationHandler invocationHandler = new InvocationHandler() {
@Override
public Object invoke(
Object proxy, Method method, Object[] arguments)
throws Throwable {
return method.invoke(bean, arguments);
}
};
invocationHandler = new PACLInvocationHandler(invocationHandler);
return ProxyUtil.newProxyInstance(
classLoader, interfaces, invocationHandler);
}
}
private static class DoBeanReferenceRefreshUtilPACL implements PACL {
@Override
public Object getNewReferencedBean(
String referencedBeanName, BeanFactory beanFactory) {
Object newReferencedBean = null;
try {
newReferencedBean = beanFactory.getBean(referencedBeanName);
}
catch (NoSuchBeanDefinitionException nsbde) {
newReferencedBean = PortalBeanLocatorUtil.locate(
referencedBeanName);
}
Object doPrivilegedBean = _doPrivilegedBeans.get(newReferencedBean);
if ((doPrivilegedBean == null) &&
DoPrivilegedFactory.isEarlyBeanReference(referencedBeanName)) {
doPrivilegedBean = DoPrivilegedFactory.wrap(newReferencedBean);
_doPrivilegedBeans.put(newReferencedBean, doPrivilegedBean);
}
if (doPrivilegedBean != null) {
newReferencedBean = doPrivilegedBean;
}
return newReferencedBean;
}
private static final Map<Object, Object> _doPrivilegedBeans =
new IdentityHashMap<>();
}
private static class DoClassLoaderUtilPACL implements ClassLoaderUtil.PACL {
@Override
public ClassLoader getAggregatePluginsClassLoader(
final String[] servletContextNames,
final boolean addContextClassLoader) {
return AccessController.doPrivileged(
new PrivilegedAction<ClassLoader>() {
@Override
public ClassLoader run() {
return _noPacl.getAggregatePluginsClassLoader(
servletContextNames, addContextClassLoader);
}
});
}
@Override
public ClassLoader getClassLoader(final Class<?> clazz) {
return AccessController.doPrivileged(
new PrivilegedAction<ClassLoader>() {
@Override
public ClassLoader run() {
return _noPacl.getClassLoader(clazz);
}
});
}
@Override
public ClassLoader getContextClassLoader() {
return AccessController.doPrivileged(
new PrivilegedAction<ClassLoader>() {
@Override
public ClassLoader run() {
return _noPacl.getContextClassLoader();
}
});
}
@Override
public ClassLoader getPluginClassLoader(
final String servletContextName) {
return AccessController.doPrivileged(
new PrivilegedAction<ClassLoader>() {
@Override
public ClassLoader run() {
return _noPacl.getPluginClassLoader(servletContextName);
}
});
}
@Override
public ClassLoader getPortalClassLoader() {
return AccessController.doPrivileged(
new PrivilegedAction<ClassLoader>() {
@Override
public ClassLoader run() {
return _noPacl.getPortalClassLoader();
}
});
}
@Override
public void setContextClassLoader(final ClassLoader classLoader) {
AccessController.doPrivileged(
new PrivilegedAction<Void>() {
@Override
public Void run() {
_noPacl.setContextClassLoader(classLoader);
return null;
}
});
}
private final ClassLoaderUtil.PACL _noPacl =
new ClassLoaderUtil.NoPACL();
}
private static class DoDataAccessPACL implements DataAccess.PACL {
@Override
public DataSource getDataSource() {
return AccessController.doPrivileged(
new PrivilegedAction<DataSource>() {
@Override
public DataSource run() {
return InfrastructureUtil.getDataSource();
}
});
}
@Override
public DataSource getDataSource(final String location)
throws NamingException {
try {
return AccessController.doPrivileged(
new PrivilegedExceptionAction<DataSource>() {
@Override
public DataSource run() throws Exception {
Properties properties = PropsUtil.getProperties(
PropsKeys.JNDI_ENVIRONMENT, true);
Context context = new InitialContext(properties);
return (DataSource)JNDIUtil.lookup(
context, location);
}
});
}
catch (PrivilegedActionException pae) {
throw (NamingException)pae.getException();
}
}
}
private static class DoDataSourceFactoryImplPACL
implements DataSourceFactoryImpl.PACL {
@Override
public DataSource getDataSource(DataSource dataSource) {
return new PACLDataSource(dataSource);
}
}
private static class DoDirectRequestDispatcherFactoryImplPACL
implements DirectRequestDispatcherFactoryImpl.PACL {
@Override
public RequestDispatcher getRequestDispatcher(
ServletContext servletContext,
RequestDispatcher requestDispatcher) {
return new PACLRequestDispatcherWrapper(
servletContext, requestDispatcher);
}
}
private static class DoDoPrivilegedPACL implements DoPrivilegedUtil.PACL {
@Override
public <T> T wrap(PrivilegedAction<T> privilegedAction) {
return DoPrivilegedFactory.wrap(
AccessController.doPrivileged(privilegedAction));
}
@Override
public <T> T wrap(
PrivilegedExceptionAction<T> privilegedExceptionAction)
throws Exception {
return DoPrivilegedFactory.wrap(
AccessController.doPrivileged(privilegedExceptionAction));
}
@Override
public <T> T wrap(T t) {
return DoPrivilegedFactory.wrap(t);
}
@Override
public <T> T wrapWhenActive(T t) {
return DoPrivilegedFactory.wrap(t);
}
}
private static class DoHotDeployImplPACL implements HotDeployImpl.PACL {
@Override
public void initPolicy(
String contextName, URLContainer urlContainer,
ClassLoader classLoader, Properties properties) {
PACLPolicy paclPolicy = PACLPolicyManager.buildPACLPolicy(
contextName, urlContainer, classLoader, properties);
PACLPolicyManager.register(classLoader, paclPolicy);
}
@Override
public void unregister(ClassLoader classLoader) {
PACLPolicyManager.unregister(classLoader);
}
}
private static class DoPortalBeanLocatorUtilPACL
implements PortalBeanLocatorUtil.PACL {
@Override
public ClassLoader getBeanLocatorClassLoader(
final BeanLocator beanLocator) {
return AccessController.doPrivileged(
new PrivilegedAction<ClassLoader>() {
@Override
public ClassLoader run() {
return beanLocator.getClassLoader();
}
});
}
@Override
public ClassLoader getContextClassLoader(final Thread currentThread) {
return AccessController.doPrivileged(
new PrivilegedAction<ClassLoader>() {
@Override
public ClassLoader run() {
return currentThread.getContextClassLoader();
}
});
}
@Override
public void setContextClassLoader(
final Thread currentThread, final ClassLoader classLoader) {
AccessController.doPrivileged(
new PrivilegedAction<Void>() {
@Override
public Void run() {
currentThread.setContextClassLoader(classLoader);
return null;
}
});
}
}
private static class DoPortalFilePermissionPACL
implements PortalFilePermission.PACL {
@Override
public void checkCopy(String source, String destination) {
SecurityManager securityManager = System.getSecurityManager();
if (securityManager == null) {
return;
}
if (Validator.isNotNull(source)) {
securityManager.checkRead(source);
}
if (Validator.isNull(destination)) {
return;
}
securityManager.checkWrite(destination);
}
@Override
public void checkDelete(String path) {
SecurityManager securityManager = System.getSecurityManager();
if (securityManager == null) {
return;
}
if (Validator.isNull(path)) {
return;
}
securityManager.checkDelete(path);
}
@Override
public void checkMove(String source, String destination) {
SecurityManager securityManager = System.getSecurityManager();
if (securityManager == null) {
return;
}
if (Validator.isNotNull(source)) {
securityManager.checkRead(source);
securityManager.checkDelete(source);
}
if (Validator.isNull(destination)) {
return;
}
securityManager.checkWrite(destination);
securityManager.checkDelete(destination);
}
@Override
public void checkRead(String path) {
SecurityManager securityManager = System.getSecurityManager();
if (securityManager == null) {
return;
}
if (Validator.isNull(path)) {
return;
}
securityManager.checkRead(path);
}
@Override
public void checkWrite(String path) {
SecurityManager securityManager = System.getSecurityManager();
if (securityManager == null) {
return;
}
if (Validator.isNull(path)) {
return;
}
securityManager.checkWrite(path);
}
}
private static class DoPortalHookPermissionPACL
implements PortalHookPermission.PACL {
@Override
public void checkPermission(
String name, ClassLoader portletClassLoader, Object subject) {
PACLPolicy paclPolicy = PACLPolicyManager.getPACLPolicy(
portletClassLoader);
if (paclPolicy == null) {
return;
}
Permission permission = new PortalHookPermission(
name, portletClassLoader, subject);
if (!paclPolicy.implies(permission)) {
throw new SecurityException(permission.toString());
}
}
}
private static class DoPortalMessageBusPermissionPACL
implements PortalMessageBusPermission.PACL {
@Override
public void checkListen(String destinationName) {
SecurityManager securityManager = System.getSecurityManager();
if (securityManager == null) {
return;
}
Permission permission = new PortalMessageBusPermission(
PACLConstants.PORTAL_MESSAGE_BUS_PERMISSION_LISTEN,
destinationName);
securityManager.checkPermission(permission);
}
@Override
public void checkSend(String destinationName) {
SecurityManager securityManager = System.getSecurityManager();
if (securityManager == null) {
return;
}
Permission permission = new PortalMessageBusPermission(
PACLConstants.PORTAL_MESSAGE_BUS_PERMISSION_SEND,
destinationName);
securityManager.checkPermission(permission);
}
}
private static class DoPortalRuntimePermissionPACL
implements PortalRuntimePermission.PACL {
@Override
public void checkDynamicQuery(Class<?> implClass) {
SecurityManager securityManager = System.getSecurityManager();
if (securityManager == null) {
return;
}
ClassLoader classLoader = ClassLoaderUtil.getClassLoader(implClass);
PACLPolicy paclPolicy = PACLPolicyManager.getPACLPolicy(
classLoader);
if (paclPolicy == PACLUtil.getPACLPolicy()) {
return;
}
String contextName = "portal";
if (paclPolicy != null) {
contextName = paclPolicy.getContextName();
}
Permission permission = new PortalRuntimePermission(
PACLConstants.PORTAL_RUNTIME_PERMISSION_GET_CLASSLOADER, null,
contextName);
securityManager.checkPermission(permission);
}
@Override
public void checkExpandoBridge(String className) {
SecurityManager securityManager = System.getSecurityManager();
if (securityManager == null) {
return;
}
Permission permission = new PortalRuntimePermission(
PACLConstants.PORTAL_RUNTIME_PERMISSION_EXPANDO_BRIDGE, null,
className);
securityManager.checkPermission(permission);
}
@Override
public void checkGetBeanProperty(
String servletContextName, Class<?> clazz, String property) {
SecurityManager securityManager = System.getSecurityManager();
if (securityManager == null) {
return;
}
Class<?> callerClass = Reflection.getCallerClass(5);
if (clazz == callerClass) {
// The bean is calling its own getBean method
return;
}
clazz = PACLUtil.getClass(clazz);
Permission permission = new PortalRuntimePermission(
PACLConstants.PORTAL_RUNTIME_PERMISSION_GET_BEAN_PROPERTY,
servletContextName, clazz.getName(), property);
securityManager.checkPermission(permission);
}
@Override
public void checkGetClassLoader(String classLoaderReferenceId) {
SecurityManager securityManager = System.getSecurityManager();
if (securityManager == null) {
return;
}
if (Validator.isNull(classLoaderReferenceId)) {
classLoaderReferenceId = "portal";
}
Permission permission = new PortalRuntimePermission(
PACLConstants.PORTAL_RUNTIME_PERMISSION_GET_CLASSLOADER, null,
classLoaderReferenceId);
securityManager.checkPermission(permission);
}
@Override
public void checkPortletBagPool(String portletId) {
SecurityManager securityManager = System.getSecurityManager();
if (securityManager == null) {
return;
}
Permission permission = new PortalRuntimePermission(
PACLConstants.PORTAL_RUNTIME_PERMISSION_PORTLET_BAG_POOL, null,
portletId);
securityManager.checkPermission(permission);
}
@Override
public void checkSearchEngine(String searchEngineId) {
SecurityManager securityManager = System.getSecurityManager();
if (securityManager == null) {
return;
}
Permission permission = new PortalRuntimePermission(
PACLConstants.PORTAL_RUNTIME_PERMISSION_SEARCH_ENGINE, null,
searchEngineId);
securityManager.checkPermission(permission);
}
@Override
public void checkSetBeanProperty(
String servletContextName, Class<?> clazz, String property) {
SecurityManager securityManager = System.getSecurityManager();
if (securityManager == null) {
return;
}
clazz = PACLUtil.getClass(clazz);
Permission permission = new PortalRuntimePermission(
PACLConstants.PORTAL_RUNTIME_PERMISSION_SET_BEAN_PROPERTY,
servletContextName, clazz.getName(), property);
securityManager.checkPermission(permission);
}
@Override
public void checkThreadPoolExecutor(String name) {
SecurityManager securityManager = System.getSecurityManager();
if (securityManager == null) {
return;
}
Permission permission = new PortalRuntimePermission(
PACLConstants.PORTAL_RUNTIME_PERMISSION_THREAD_POOL_EXECUTOR,
null, name);
securityManager.checkPermission(permission);
}
}
private static class DoPortalServicePermissionPACL
implements PortalServicePermission.PACL {
@Override
public void checkService(
Object object, Method method, Object[] arguments) {
SecurityManager securityManager = System.getSecurityManager();
if (securityManager == null) {
return;
}
String methodName = method.getName();
if (methodName.equals("invokeMethod")) {
methodName = (String)arguments[0];
}
Class<?> clazz = PACLUtil.getClass(object);
String className = PACLUtil.getServiceInterfaceName(
clazz.getName());
ClassLoader classLoader = ClassLoaderUtil.getClassLoader(clazz);
PACLPolicy paclPolicy = PACLPolicyManager.getPACLPolicy(
classLoader);
if ((paclPolicy != null) &&
(paclPolicy == PACLUtil.getPACLPolicy())) {
return;
}
String contextName = "portal";
if (paclPolicy != null) {
contextName = paclPolicy.getContextName();
}
PortalServicePermission portalServicePermission =
new PortalServicePermission(
PACLConstants.PORTAL_SERVICE_PERMISSION_SERVICE,
contextName, className, methodName);
securityManager.checkPermission(portalServicePermission);
}
}
private static class DoPortalSocketPermissionPACL
implements PortalSocketPermission.PACL {
@Override
public void checkPermission(String host, String action) {
SecurityManager securityManager = System.getSecurityManager();
if (securityManager == null) {
return;
}
Permission permission = new SocketPermission(host, action);
securityManager.checkPermission(permission);
}
}
private static class DoPortletApplicationContextPACL
implements PortletApplicationContext.PACL {
@Override
public ClassLoader getBeanClassLoader() {
return DoPrivilegedFactory.wrap(
new PreloadClassLoader(
PortletClassLoaderUtil.getClassLoader(), _classes));
}
private static final Map<String, Class<?>> _classes = new HashMap<>();
static {
for (String className :
PropsValues.
PORTAL_SECURITY_MANAGER_PRELOAD_CLASSLOADER_CLASSES) {
Class<?> clazz = null;
try {
clazz = Class.forName(className);
}
catch (ClassNotFoundException cnfe) {
_log.error(cnfe, cnfe);
}
_classes.put(clazz.getName(), clazz);
}
}
}
private static class DoReferenceRegistryPACL
implements ReferenceRegistry.PACL {
@Override
public ReferenceEntry getReferenceEntry(
final Class<?> clazz, final Object object,
final String fieldName)
throws NoSuchFieldException, SecurityException {
try {
return AccessController.doPrivileged(
new PrivilegedExceptionAction<ReferenceEntry>() {
@Override
public ReferenceEntry run() throws Exception {
Field field = clazz.getDeclaredField(fieldName);
return new ReferenceEntry(object, field);
}
});
}
catch (PrivilegedActionException pae) {
Exception exception = pae.getException();
if (exception instanceof NoSuchFieldException) {
throw (NoSuchFieldException)exception;
}
throw (SecurityException)exception;
}
}
}
private static class DoServiceBeanAopProxyPACL
implements ServiceBeanAopProxy.PACL {
@Override
public InvocationHandler getInvocationHandler(
InvocationHandler invocationHandler,
AdvisedSupport advisedSupport) {
return new PACLInvocationHandler(invocationHandler, advisedSupport);
}
}
private static class DoServiceComponentLocalServiceImplPACL
implements ServiceComponentLocalServiceImpl.PACL {
@Override
public void doUpgradeDB(
DoUpgradeDBPrivilegedExceptionAction
doUpgradeDBPrivilegedExceptionAction)
throws Exception {
ProtectionDomain protectionDomain = new ProtectionDomain(
null, null,
doUpgradeDBPrivilegedExceptionAction.getClassLoader(), null);
AccessControlContext accessControlContext =
new AccessControlContext(
new ProtectionDomain[] {protectionDomain});
AccessController.doPrivileged(
doUpgradeDBPrivilegedExceptionAction, accessControlContext);
}
}
private static class DoTemplateContextHelperPACL
implements TemplateContextHelper.PACL {
@Override
public TemplateControlContext getTemplateControlContext() {
PACLPolicy paclPolicy = PACLUtil.getPACLPolicy();
ClassLoader contextClassLoader =
ClassLoaderUtil.getContextClassLoader();
if (paclPolicy == null) {
paclPolicy = PACLPolicyManager.getPACLPolicy(
contextClassLoader);
}
if ((paclPolicy == null) || !paclPolicy.isActive()) {
return new TemplateControlContext(null, contextClassLoader);
}
ProtectionDomain protectionDomain = new ProtectionDomain(
null, null, paclPolicy.getClassLoader(), null);
AccessControlContext accessControlContext =
new AccessControlContext(
new ProtectionDomain[] {protectionDomain});
return new TemplateControlContext(
accessControlContext, paclPolicy.getClassLoader());
}
}
private static class PermissionAction implements PrivilegedAction<Void> {
public PermissionAction(
MethodHandle checkPermissionMethodHandle, Permission permission,
Object context) {
_checkPermissionMethodHandle = checkPermissionMethodHandle;
_permission = permission;
_context = context;
}
@Override
public Void run() {
try {
_checkPermissionMethodHandle.invokeExact(_permission, _context);
}
catch (Throwable t) {
ReflectionUtil.throwException(t);
}
return null;
}
private final MethodHandle _checkPermissionMethodHandle;
private final Object _context;
private final Permission _permission;
}
}