/*
* Copyright (C) 2010 eXo Platform SAS.
*
* This 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 software 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.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.exoplatform.web.security.proxy;
import java.net.URI;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.regex.Pattern;
import javax.servlet.http.HttpServletRequest;
import org.exoplatform.container.PortalContainer;
import org.exoplatform.container.xml.InitParams;
import org.exoplatform.container.xml.ValuesParam;
import org.gatein.common.logging.Logger;
import org.gatein.common.logging.LoggerFactory;
/**
* The proxy filter service is used for filtering http access when it is performed by GateIn. The following rules applies to the
* filtering:
*
* <ul>
* <li>Same host URI grants access</li>
* <li>A black list match of the host denies access</li>
* <li>A white list match of the host grants access</li>
* <li>Access is denied</li>
* </ul>
*
* The service is configured by
* <ul>
* <li>a <code>white-list</code> parameter that specifies a list of white list rules</li>
* <li>a <code>black-list</code> parameter that specifies a list of black list rules</li>
* </ul>
*
* Rules are trimmed and the wildcard character can be used to match any number of character.
*
* @author <a href="mailto:julien.viet@exoplatform.com">Julien Viet</a>
* @version $Revision$
*/
public class ProxyFilterService {
/** . */
private static final Logger log = LoggerFactory.getLogger(ProxyFilterService.class);
/** . */
private final List<Pattern> whiteList;
/** . */
private final List<Pattern> blackList;
public ProxyFilterService(InitParams params) {
this.whiteList = createList(params.getValuesParam("white-list"));
this.blackList = createList(params.getValuesParam("black-list"));
// A bit of logging
log.debug("Proxy filter service white list " + whiteList);
log.debug("Proxy filter service black list " + blackList);
}
private List<Pattern> createList(ValuesParam values) {
if (values != null) {
ArrayList<Pattern> patterns = new ArrayList<Pattern>();
for (Object value : values.getValues()) {
String s = ((String) value).trim();
StringBuilder sb = new StringBuilder("^");
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
switch (c) {
case '*':
sb.append(".*");
break;
case '[':
case '\\':
case '^':
case '$':
case '.':
case '|':
case '?':
case '+':
case '(':
case ')':
sb.append("\\");
sb.append(c);
break;
default:
sb.append(c);
break;
}
}
sb.append("$");
Pattern pattern = Pattern.compile(sb.toString());
patterns.add(pattern);
}
return Collections.unmodifiableList(patterns);
} else {
return Collections.emptyList();
}
}
/**
* Returns true if access to a remote URI should be granted.
*
* @param request the servlet request doing the request
* @param container the portal container associated with the request
* @param remoteURI the remote URI to check
* @return the access to the remote URI
*/
public boolean accept(HttpServletRequest request, PortalContainer container, URI remoteURI) {
boolean trace = log.isTraceEnabled();
//
String remoteHost = remoteURI.getHost();
// Filter based on same server name
String remoteServerName = request.getServerName();
if (remoteHost.equals(remoteServerName)) {
if (trace) {
log.trace("Same host matching for URI " + remoteURI);
}
return true;
}
// Otherwise go through black list first
for (int i = 0; i < blackList.size(); i++) {
Pattern pattern = blackList.get(i);
boolean rejected = pattern.matcher(remoteHost).matches();
if (trace) {
log.trace("Black list " + pattern + (rejected ? " matched URI " : " did not match URI") + remoteURI);
}
if (rejected) {
log.info("URL for the gadget is blacklisted (pattern: "+pattern+"). Access to its contents has been blocked. URL: " + remoteURI);
return false;
}
}
// Finally go through white list first
for (int i = 0; i < whiteList.size(); i++) {
Pattern pattern = whiteList.get(i);
boolean accepted = pattern.matcher(remoteHost).matches();
if (trace) {
log.trace("White list " + pattern + (accepted ? " matched URI " : " did not match URI") + remoteURI);
}
if (accepted) {
return true;
}
}
//
log.info("URL for the gadget is not white-listed. Access to its contents has been blocked. URL: " + remoteURI);
//
return false;
}
}