/*
* LinShare is an open source filesharing software, part of the LinPKI software
* suite, developed by Linagora.
*
* Copyright (C) 2015 LINAGORA
*
* This program is free software: you can redistribute it and/or modify it under
* the terms of the GNU Affero General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version, provided you comply with the Additional Terms applicable for
* LinShare software by Linagora pursuant to Section 7 of the GNU Affero General
* Public License, subsections (b), (c), and (e), pursuant to which you must
* notably (i) retain the display of the “LinShare™” trademark/logo at the top
* of the interface window, the display of the “You are using the Open Source
* and free version of LinShare™, powered by Linagora © 2009–2015. Contribute to
* Linshare R&D by subscribing to an Enterprise offer!” infobox and in the
* e-mails sent with the Program, (ii) retain all hypertext links between
* LinShare and linshare.org, between linagora.com and Linagora, and (iii)
* refrain from infringing Linagora intellectual property rights over its
* trademarks and commercial brands. Other Additional Terms apply, see
* <http://www.linagora.com/licenses/> for more details.
*
* This program 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 Affero General Public License for more
* details.
*
* You should have received a copy of the GNU Affero General Public License and
* its applicable Additional Terms for LinShare along with this program. If not,
* see <http://www.gnu.org/licenses/> for the GNU Affero General Public License
* version 3 and <http://www.linagora.com/licenses/> for the Additional Terms
* applicable to LinShare software.
*/
package org.linagora.linshare.core.service.impl;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.apache.commons.lang.Validate;
import org.linagora.linshare.core.business.service.DomainPolicyBusinessService;
import org.linagora.linshare.core.domain.constants.DomainAccessRuleType;
import org.linagora.linshare.core.domain.entities.AbstractDomain;
import org.linagora.linshare.core.domain.entities.AllowDomain;
import org.linagora.linshare.core.domain.entities.DenyDomain;
import org.linagora.linshare.core.domain.entities.DomainAccessRule;
import org.linagora.linshare.core.domain.entities.DomainPolicy;
import org.linagora.linshare.core.exception.BusinessErrorCode;
import org.linagora.linshare.core.exception.BusinessException;
import org.linagora.linshare.core.service.DomainPolicyService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class DomainPolicyServiceImpl implements DomainPolicyService {
private static final Logger logger = LoggerFactory
.getLogger(DomainPolicyServiceImpl.class);
private final DomainPolicyBusinessService domainPolicyBusinessService;
public DomainPolicyServiceImpl(
DomainPolicyBusinessService domainPolicyBusinessService) {
super();
this.domainPolicyBusinessService = domainPolicyBusinessService;
}
@Override
public DomainPolicy delete(String policyToDelete) throws BusinessException {
return domainPolicyBusinessService.delete(policyToDelete);
}
@Override
public boolean policyIsDeletable(String policyToDelete) {
return domainPolicyBusinessService.policyIsDeletable(policyToDelete);
}
@Override
public DomainPolicy create(DomainPolicy domainPolicy)
throws BusinessException {
if (domainPolicy == null
|| domainPolicy.getDomainAccessPolicy() == null)
throw new BusinessException(
"Creating a domain policy without an associated access policy is impossible");
DomainPolicy policy = domainPolicyBusinessService.find(domainPolicy.getUuid());
if (policy != null)
throw new BusinessException(
BusinessErrorCode.DOMAIN_POLICY_ALREADY_EXISTS,
"Domain policy with identifier : "
+ domainPolicy.getUuid() + " already exists.");
return domainPolicyBusinessService.create(domainPolicy);
}
@Override
public DomainPolicy update(DomainPolicy domainPolicy) throws BusinessException {
return domainPolicyBusinessService.update(domainPolicy);
}
@Override
public DomainPolicy find(String identifier) {
Validate.notEmpty(identifier);
DomainPolicy domainPolicy = domainPolicyBusinessService
.find(identifier);
if (domainPolicy == null)
throw new BusinessException(
BusinessErrorCode.DOMAIN_POLICY_NOT_FOUND,
"Domain policy with identifer: " + identifier
+ " not found");
return domainPolicy;
}
@Override
public List<DomainPolicy> findAll() throws BusinessException {
return domainPolicyBusinessService.findAll();
}
private List<AbstractDomain> getAuthorizedDomain(AbstractDomain domain,
List<DomainAccessRule> rules) {
Set<AbstractDomain> set = new HashSet<AbstractDomain>();
set.add(domain);
return getAuthorizedDomain(set, rules);
}
private List<AbstractDomain> getAuthorizedDomain(
Set<AbstractDomain> domains, List<DomainAccessRule> rules) {
List<AbstractDomain> includes = new ArrayList<AbstractDomain>();
List<AbstractDomain> excludes = new ArrayList<AbstractDomain>();
for (AbstractDomain domain : domains) {
logger.debug("check:domain : " + domain.toString());
for (DomainAccessRule domainAccessRule : rules) {
logger.debug("check:domainAccessRule : "
+ domainAccessRule.getDomainAccessRuleType().toString());
if (domainAccessRule.getDomainAccessRuleType().equals(
DomainAccessRuleType.ALLOW_ALL)) {
// logger.debug("check:domainAccessRule : ALLOW_ALL");
// Allow domain without any check
if (!includes.contains(domain)
&& !excludes.contains(domain)) {
includes.add(domain);
}
// This rule should me the last one
break;
} else if (domainAccessRule.getDomainAccessRuleType().equals(
DomainAccessRuleType.DENY_ALL)) {
// logger.debug("check:domainAccessRule : DENY_ALL");
// Deny domain without any check
if (!excludes.contains(domain)) {
excludes.add(domain);
}
// This rule should me the last one
break;
} else if (domainAccessRule.getDomainAccessRuleType().equals(
DomainAccessRuleType.ALLOW)) {
// logger.debug("check:domainAccessRule : ALLOW");
// Allow domain
AllowDomain allowDomain = (AllowDomain) domainAccessRule;
if (allowDomain.getDomain().equals(domain)
&& !includes.contains(domain)) {
logger.debug(" ALLOW : " + domain.getUuid());
includes.add(domain);
}
} else if (domainAccessRule.getDomainAccessRuleType().equals(
DomainAccessRuleType.DENY)) {
// Deny domain
// logger.debug("check:domainAccessRule : DENY");
DenyDomain denyDomain = (DenyDomain) domainAccessRule;
if (denyDomain.getDomain().equals(domain)
&& !excludes.contains(domain)) {
logger.debug(" DENY : " + domain.getUuid());
excludes.add(domain);
} else {
includes.add(domain);
}
}
}
}
return includes;
}
@Override
public boolean isAuthorizedToCommunicateWithItSelf(AbstractDomain domain) {
logger.debug("Begin isAuthorizedToCommunicateWithItSelf : " + domain);
List<AbstractDomain> result = getAuthorizedDomain(domain, domain
.getPolicy().getDomainAccessPolicy().getRules());
if (result != null && result.size() == 1) {
logger.debug("Domain '" + domain.getUuid()
+ "' is authorized to communicate with itself.");
return true;
}
logger.debug("Domain '" + domain.getUuid()
+ "' is not authorized to communicate with itself.");
logger.debug("End isAuthorizedToCommunicateWithItSelf : " + domain);
return false;
}
@Override
public boolean isAuthorizedToCommunicateWithItsParent(AbstractDomain domain) {
logger.debug("Begin isAuthorizedToCommunicateWithItsParent : " + domain);
if (domain.getParentDomain() != null) {
List<AbstractDomain> result = getAuthorizedDomain(
domain.getParentDomain(), domain.getPolicy()
.getDomainAccessPolicy().getRules());
if (result != null && result.size() == 1) {
logger.debug("Domain '" + domain.getUuid()
+ "' is authorized to communicate with its parent.");
return true;
}
}
logger.debug("Domain '" + domain.getUuid()
+ "' is not authorized to communicate with its parent.");
logger.debug("End isAuthorizedToCommunicateWithItsParent : " + domain);
return false;
}
@Override
public List<AbstractDomain> getAuthorizedSubDomain(AbstractDomain domain) {
logger.debug("Begin public getAuthorizedSubDomain : " + domain);
List<AbstractDomain> result = new ArrayList<AbstractDomain>();
List<DomainAccessRule> rules = domain.getPolicy()
.getDomainAccessPolicy().getRules();
// Check for communication with subdomains.
if (domain.getSubdomain() != null) {
result.addAll(getAuthorizedDomain(domain.getSubdomain(), rules));
}
logger.debug("domain result list size : " + result.size());
for (AbstractDomain abstractDomain : result) {
logger.debug("result : " + abstractDomain.getUuid());
}
logger.debug("End public getAuthorizedSubDomain : " + domain);
return result;
}
@Override
public List<AbstractDomain> getAuthorizedSibblingDomain(
AbstractDomain domain) {
logger.debug("Begin getAuthorizedSibblingDomain : " + domain);
List<AbstractDomain> result = new ArrayList<AbstractDomain>();
List<DomainAccessRule> rules = domain.getPolicy()
.getDomainAccessPolicy().getRules();
// Check for communication with siblings.
if (domain.getParentDomain() != null) {
result.addAll(getAuthorizedDomain(domain.getParentDomain()
.getSubdomain(), rules));
}
logger.debug("domain result list size : " + result.size());
for (AbstractDomain abstractDomain : result) {
logger.debug("result : " + abstractDomain.getUuid());
}
logger.debug("End getAuthorizedSibblingDomain : " + domain);
return result;
}
private List<AbstractDomain> getAllAuthorizedDomain(AbstractDomain domain,
List<DomainAccessRule> rules) {
List<AbstractDomain> result = new ArrayList<AbstractDomain>();
// Step 1 : check for self communication
result.addAll(getAuthorizedDomain(domain, rules));
// Step 2 : check for communication with sub domains.
if (domain.getSubdomain() != null) {
for (AbstractDomain sub : domain.getSubdomain()) {
for (AbstractDomain d : getAllAuthorizedDomain(sub, rules)) {
if (!result.contains(d)) {
result.add(d);
}
}
}
}
return result;
}
private List<AbstractDomain> getAllAuthorizedDomainReverse(
AbstractDomain domain, List<DomainAccessRule> rules) {
List<AbstractDomain> result = new ArrayList<AbstractDomain>();
if (domain.getParentDomain() != null) {
result.addAll(getAllAuthorizedDomainReverse(
domain.getParentDomain(), rules));
}
// Step 1 : check for self communication
result.addAll(getAuthorizedDomain(domain, rules));
// Step 2 : check for communication with sub domains.
if (domain.getSubdomain() != null) {
for (AbstractDomain sub : domain.getSubdomain()) {
for (AbstractDomain d : getAllAuthorizedDomain(sub, rules)) {
if (!result.contains(d)) {
result.add(d);
}
}
}
}
return result;
}
@Override
public List<AbstractDomain> getAllAuthorizedDomain(AbstractDomain domain) {
logger.debug("Begin getAllAuthorizedDomain : " + domain);
List<AbstractDomain> result = new ArrayList<AbstractDomain>();
List<DomainAccessRule> rules = domain.getPolicy()
.getDomainAccessPolicy().getRules();
for (AbstractDomain d : getAllAuthorizedDomain(domain, rules)) {
if (!result.contains(d)) {
result.add(d);
}
}
for (AbstractDomain d : getAllAuthorizedDomainReverse(domain, rules)) {
if (!result.contains(d)) {
result.add(d);
}
}
logger.debug("domain result list size : " + result.size());
for (AbstractDomain abstractDomain : result) {
logger.debug("result : " + abstractDomain.getUuid());
}
logger.debug("End getAllAuthorizedDomain : " + domain);
return result;
}
}