/**
* 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.service.access.policy.internal;
import com.liferay.portal.kernel.exception.PortalException;
import com.liferay.portal.kernel.module.configuration.ConfigurationException;
import com.liferay.portal.kernel.module.configuration.ConfigurationProvider;
import com.liferay.portal.kernel.security.access.control.AccessControlPolicy;
import com.liferay.portal.kernel.security.access.control.AccessControlUtil;
import com.liferay.portal.kernel.security.access.control.AccessControlled;
import com.liferay.portal.kernel.security.access.control.BaseAccessControlPolicy;
import com.liferay.portal.kernel.security.auth.AccessControlContext;
import com.liferay.portal.kernel.security.auth.CompanyThreadLocal;
import com.liferay.portal.kernel.security.auth.verifier.AuthVerifierResult;
import com.liferay.portal.kernel.security.service.access.policy.ServiceAccessPolicyThreadLocal;
import com.liferay.portal.kernel.settings.CompanyServiceSettingsLocator;
import com.liferay.portal.kernel.util.CharPool;
import com.liferay.portal.kernel.util.StringPool;
import com.liferay.portal.kernel.util.Validator;
import com.liferay.portal.security.service.access.policy.configuration.SAPConfiguration;
import com.liferay.portal.security.service.access.policy.constants.SAPConstants;
import com.liferay.portal.security.service.access.policy.model.SAPEntry;
import com.liferay.portal.security.service.access.policy.service.SAPEntryLocalService;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
/**
* @author Mika Koivisto
*/
@Component(service = AccessControlPolicy.class)
public class SAPAccessControlPolicy extends BaseAccessControlPolicy {
@Override
public void onServiceRemoteAccess(
Method method, Object[] arguments,
AccessControlled accessControlled)
throws SecurityException {
if (isChecked()) {
return;
}
List<String> serviceAccessPolicyNames = new ArrayList<>();
serviceAccessPolicyNames.addAll(getActiveServiceAccessPolicyNames());
serviceAccessPolicyNames.addAll(
getDefaultServiceAccessPolicyNames(
CompanyThreadLocal.getCompanyId()));
serviceAccessPolicyNames.addAll(
getSystemServiceAccessPolicyNames(
CompanyThreadLocal.getCompanyId()));
Set<String> allowedServiceSignatures = loadAllowedServiceSignatures(
CompanyThreadLocal.getCompanyId(), serviceAccessPolicyNames);
Class<?> clazz = method.getDeclaringClass();
checkAccess(
allowedServiceSignatures, clazz.getName(), method.getName());
}
protected void checkAccess(
Set<String> allowedServiceSignatures, String className,
String methodName) {
if (allowedServiceSignatures.contains(StringPool.STAR)) {
return;
}
if (allowedServiceSignatures.contains(className)) {
return;
}
String classNameAndMethodName = className.concat(
StringPool.POUND).concat(methodName);
if (allowedServiceSignatures.contains(classNameAndMethodName)) {
return;
}
for (String allowedServiceSignature : allowedServiceSignatures) {
if (matches(className, methodName, allowedServiceSignature)) {
return;
}
}
throw new SecurityException(
"Access denied to " + classNameAndMethodName);
}
protected List<String> getActiveServiceAccessPolicyNames() {
List<String> activeServiceAccessPolicyNames =
ServiceAccessPolicyThreadLocal.getActiveServiceAccessPolicyNames();
if (activeServiceAccessPolicyNames == null) {
activeServiceAccessPolicyNames = new ArrayList<>();
ServiceAccessPolicyThreadLocal.setActiveServiceAccessPolicyNames(
activeServiceAccessPolicyNames);
}
return activeServiceAccessPolicyNames;
}
protected List<String> getDefaultServiceAccessPolicyNames(long companyId) {
List<SAPEntry> defaultSAPEntries =
_sapEntryLocalService.getDefaultSAPEntries(companyId, true);
List<String> defaultServiceAccessPolicyNames = new ArrayList<>(
defaultSAPEntries.size());
for (SAPEntry sapEntry : defaultSAPEntries) {
defaultServiceAccessPolicyNames.add(sapEntry.getName());
}
return defaultServiceAccessPolicyNames;
}
protected List<String> getSystemServiceAccessPolicyNames(long companyId) {
List<String> systemServiceAccessPolicyNames = new ArrayList<>(2);
SAPConfiguration sapConfiguration = null;
try {
sapConfiguration = _configurationProvider.getConfiguration(
SAPConfiguration.class,
new CompanyServiceSettingsLocator(
companyId, SAPConstants.SERVICE_NAME));
}
catch (ConfigurationException ce) {
throw new SecurityException(
"Unable to get service access policy configuration", ce);
}
if (!sapConfiguration.useSystemSAPEntries()) {
return systemServiceAccessPolicyNames;
}
systemServiceAccessPolicyNames.add(
sapConfiguration.systemDefaultSAPEntryName());
boolean passwordBasedAuthentication = false;
AccessControlContext accessControlContext =
AccessControlUtil.getAccessControlContext();
if (accessControlContext != null) {
AuthVerifierResult authVerifierResult =
accessControlContext.getAuthVerifierResult();
if (authVerifierResult != null) {
passwordBasedAuthentication =
authVerifierResult.isPasswordBasedAuthentication();
}
}
if (passwordBasedAuthentication) {
systemServiceAccessPolicyNames.add(
sapConfiguration.systemUserPasswordSAPEntryName());
}
return systemServiceAccessPolicyNames;
}
protected boolean isChecked() {
AccessControlContext accessControlContext =
AccessControlUtil.getAccessControlContext();
if (accessControlContext != null) {
Map<String, Object> settings = accessControlContext.getSettings();
int serviceDepth = (Integer)settings.get(
AccessControlContext.Settings.SERVICE_DEPTH.toString());
if (serviceDepth > 1) {
return true;
}
}
return false;
}
protected Set<String> loadAllowedServiceSignatures(
long companyId, List<String> serviceAccessPolicyNames) {
Set<String> allowedServiceSignatures = new HashSet<>();
for (String serviceAccessPolicyName : serviceAccessPolicyNames) {
try {
SAPEntry sapEntry = _sapEntryLocalService.getSAPEntry(
companyId, serviceAccessPolicyName);
if (!sapEntry.isEnabled()) {
continue;
}
allowedServiceSignatures.addAll(
sapEntry.getAllowedServiceSignaturesList());
}
catch (PortalException pe) {
throw new SecurityException(pe);
}
}
return allowedServiceSignatures;
}
protected boolean matches(
String className, String methodName, String allowedServiceSignature) {
String allowedClassName = null;
String allowedMethodName = null;
int index = allowedServiceSignature.indexOf(CharPool.POUND);
if (index > -1) {
allowedClassName = allowedServiceSignature.substring(0, index);
allowedMethodName = allowedServiceSignature.substring(index + 1);
}
else {
allowedClassName = allowedServiceSignature;
}
boolean wildcardMatchClass = false;
if (Validator.isNotNull(allowedClassName) &&
allowedClassName.endsWith(StringPool.STAR)) {
allowedClassName = allowedClassName.substring(
0, allowedClassName.length() - 1);
wildcardMatchClass = true;
}
boolean wildcardMatchMethod = false;
if (Validator.isNotNull(allowedMethodName) &&
allowedMethodName.endsWith(StringPool.STAR)) {
allowedMethodName = allowedMethodName.substring(
0, allowedMethodName.length() - 1);
wildcardMatchMethod = true;
}
if (Validator.isNotNull(allowedClassName) &&
Validator.isNotNull(allowedMethodName)) {
if (wildcardMatchClass && !className.startsWith(allowedClassName)) {
return false;
}
else if (!wildcardMatchClass &&
!className.equals(allowedClassName)) {
return false;
}
if (wildcardMatchMethod &&
!methodName.startsWith(allowedMethodName)) {
return false;
}
else if (!wildcardMatchMethod &&
!methodName.equals(allowedMethodName)) {
return false;
}
return true;
}
else if (Validator.isNotNull(allowedClassName)) {
if (wildcardMatchClass && !className.startsWith(allowedClassName)) {
return false;
}
else if (!wildcardMatchClass &&
!className.equals(allowedClassName)) {
return false;
}
return true;
}
else if (Validator.isNotNull(allowedMethodName)) {
if (wildcardMatchMethod &&
!methodName.startsWith(allowedMethodName)) {
return false;
}
else if (!wildcardMatchMethod &&
!methodName.equals(allowedMethodName)) {
return false;
}
return true;
}
else if (wildcardMatchClass && Validator.isNull(allowedClassName)) {
return true;
}
return false;
}
@Reference(unbind = "-")
protected void setConfigurationProvider(
ConfigurationProvider configurationProvider) {
_configurationProvider = configurationProvider;
}
@Reference(unbind = "-")
protected void setSAPEntryLocalService(
SAPEntryLocalService sapEntryLocalService) {
_sapEntryLocalService = sapEntryLocalService;
}
private ConfigurationProvider _configurationProvider;
private SAPEntryLocalService _sapEntryLocalService;
}