/**
* 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.kernel.url.URLContainer;
import com.liferay.portal.kernel.util.GetterUtil;
import com.liferay.portal.kernel.util.StringPool;
import com.liferay.portal.security.lang.PortalSecurityManager;
import com.liferay.portal.security.lang.SecurityManagerUtil;
import com.liferay.portal.util.PropsValues;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.security.AccessController;
import java.security.CodeSource;
import java.security.Policy;
import java.security.PrivilegedAction;
import java.security.ProtectionDomain;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
/**
* @author Brian Wing Shun Chan
* @author Raymond Augé
*/
public class PACLPolicyManager {
public static PACLPolicy buildPACLPolicy(
String contextName, URLContainer urlContainer, ClassLoader classLoader,
Properties properties) {
String value = properties.getProperty(
"security-manager-enabled", "false");
if (value.equals("generate")) {
return new GeneratingPACLPolicy(
contextName, urlContainer, classLoader, properties);
}
if (GetterUtil.getBoolean(value)) {
return new ActivePACLPolicy(
contextName, urlContainer, classLoader, properties);
}
return new InactivePACLPolicy(
contextName, urlContainer, classLoader, properties);
}
public static PACLPolicy getDefaultPACLPolicy() {
return _defaultPACLPolicy;
}
public static PACLPolicy getPACLPolicy(ClassLoader classLoader) {
if (classLoader == null) {
return null;
}
return AccessController.doPrivileged(
new PACLPolicyPrivilegedAction(classLoader));
}
public static PACLPolicy getPACLPolicy(ProtectionDomain protectionDomain) {
if (protectionDomain == null) {
return null;
}
return AccessController.doPrivileged(
new PACLPolicyPrivilegedAction(protectionDomain));
}
public static PACLPolicy getPACLPolicy(URL locationURL) {
if (locationURL == null) {
return null;
}
return AccessController.doPrivileged(
new PACLPolicyPrivilegedAction(locationURL));
}
public static void register(
ClassLoader classLoader, PACLPolicy paclPolicy) {
List<URL> urLs = paclPolicy.getURLs();
if (classLoader instanceof URLClassLoader) {
URLClassLoader urlClassLoader = (URLClassLoader)classLoader;
for (URL url : urlClassLoader.getURLs()) {
String path = url.getPath();
if (path.startsWith(
PropsValues.LIFERAY_LIB_GLOBAL_SHARED_DIR)) {
continue;
}
urLs.add(url);
_urlPACLPolicies.put(new URLWrapper(url), paclPolicy);
}
}
URLContainer urlContainer = paclPolicy.getURLContainer();
URL rootURL = urlContainer.getResource(StringPool.SLASH);
String path = rootURL.getPath();
if (path.endsWith(StringPool.SLASH)) {
path = path.substring(0, path.length() - 1);
}
try {
URL url = new URL("file", "", -1, path);
urLs.add(url);
_urlPACLPolicies.put(new URLWrapper(url), paclPolicy);
url = new URL("file", "", -1, path + StringPool.SLASH);
urLs.add(url);
_urlPACLPolicies.put(new URLWrapper(url), paclPolicy);
url = new URL("file", "", -1, path + "/WEB-INF/classes/*");
urLs.add(url);
_urlPACLPolicies.put(new URLWrapper(url), paclPolicy);
}
catch (MalformedURLException murle) {
throw new RuntimeException(murle);
}
_classLoaderPACLPolicies.put(classLoader, paclPolicy);
_refresh();
}
public static void unregister(ClassLoader classLoader) {
PACLPolicy paclPolicy = _classLoaderPACLPolicies.remove(classLoader);
for (URL url : paclPolicy.getURLs()) {
_urlPACLPolicies.remove(url);
}
_refresh();
}
private static void _refresh() {
PortalSecurityManager portalSecurityManager =
SecurityManagerUtil.getPortalSecurityManager();
Policy policy = portalSecurityManager.getPolicy();
policy.refresh();
}
private static final Map<ClassLoader, PACLPolicy> _classLoaderPACLPolicies =
new ConcurrentHashMap<>();
private static final PACLPolicy _defaultPACLPolicy = new InactivePACLPolicy(
StringPool.BLANK, new InactiveURLContainer(),
PACLPolicyManager.class.getClassLoader(), new Properties());
private static final Map<URLWrapper, PACLPolicy> _urlPACLPolicies =
new ConcurrentHashMap<>();
private static class InactiveURLContainer implements URLContainer {
@Override
public URL getResource(String name) {
return null;
}
@Override
public Set<String> getResources(String path) {
return Collections.<String>emptySet();
}
}
private static class PACLPolicyPrivilegedAction
implements PrivilegedAction<PACLPolicy> {
public PACLPolicyPrivilegedAction(ClassLoader classLoader) {
_classLoader = classLoader;
}
public PACLPolicyPrivilegedAction(ProtectionDomain protectionDomain) {
_classLoader = protectionDomain.getClassLoader();
CodeSource codeSource = protectionDomain.getCodeSource();
if (codeSource == null) {
return;
}
_locationURL = codeSource.getLocation();
}
public PACLPolicyPrivilegedAction(URL locationURL) {
_locationURL = locationURL;
}
@Override
public PACLPolicy run() {
PACLPolicy paclPolicy = _getFromClassLoader();
if ((paclPolicy != null) || (_classLoader != null) ||
(_locationURL == null)) {
return paclPolicy;
}
return _urlPACLPolicies.get(new URLWrapper(_locationURL));
}
private PACLPolicy _getFromClassLoader() {
if (_classLoader == null) {
return null;
}
PACLPolicy paclPolicy = _classLoaderPACLPolicies.get(_classLoader);
while ((paclPolicy == null) && (_classLoader.getParent() != null)) {
_classLoader = _classLoader.getParent();
paclPolicy = _classLoaderPACLPolicies.get(_classLoader);
}
return paclPolicy;
}
private ClassLoader _classLoader;
private URL _locationURL;
}
}