Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  /*
   * Licensed to the Apache Software Foundation (ASF) under one or more
   * contributor license agreements.  See the NOTICE file distributed with
   * this work for additional information regarding copyright ownership.
   * The ASF licenses this file to You under the Apache License, Version 2.0
   * (the "License"); you may not use this file except in compliance with
   * the License.  You may obtain a copy of the License at
   *
   *      http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
 package org.apache.sling.security.impl;
 
 import java.net.URL;
 import java.util.List;
 import java.util.Set;
 
 
 import  org.osgi.framework.BundleContext;
 import  org.osgi.framework.Constants;
 import  org.osgi.framework.ServiceRegistration;
 import  org.osgi.service.component.ComponentContext;
 
 @Component(metatype=true, description="%referrer.description",
         label="%referrer.name")
 @Property(name="pattern", value="/.*", propertyPrivate=true)
 @Service(value=Filter.class)
 public class ReferrerFilter implements Filter {

    
Request header providing the clients user agent information used by isBrowserRequest(HttpServletRequest) to decide whether a request is probably sent by a browser or not.
 
     private static final String USER_AGENT = "User-Agent";

    
String contained in a USER_AGENT header indicating a Mozilla class browser. Examples of such browsers are Firefox (generally Gecko based browsers), Safari, Chrome (probably generally WebKit based browsers), and Microsoft IE.
 
     private static final String BROWSER_CLASS_MOZILLA = "Mozilla";

    
String contained in a USER_AGENT header indicating a Opera class browser. The only known browser in this class is the Opera browser.
 
     private static final String BROWSER_CLASS_OPERA = "Opera";

    
Logger.
 
     private final Logger logger = LoggerFactory.getLogger(this.getClass());

    
Default value for allow empty.
 
     private static final boolean DEFAULT_ALLOW_EMPTY = true;

    
Allow empty property.
 
     @Property(boolValue=)
     private static final String PROP_ALLOW_EMPTY = "allow.empty";

    
Allow empty property.
 
     @Property(unbounded=.)
     private static final String PROP_HOSTS = "allow.hosts";

    
Allow empty property.
 
     @Property(unbounded=., value={"POST""PUT""DELETE"})
    private static final String PROP_METHODS = "filter.methods";

    
Do we allow empty referrer?
    private boolean allowEmpty;

    
Allowed referrers
    private URL[] allowedReferrers;

    
Methods to be filtered.
    private String[] filterMethods;
    private ServiceRegistration configPrinterRegistration;

    
Create a default list of referrers
    private Set<StringgetDefaultAllowedReferrers() {
        final Set<Stringreferrers = new HashSet<String>();
        try {
            final Enumeration<NetworkInterfaceifaces = NetworkInterface.getNetworkInterfaces();
            while(ifaces.hasMoreElements()){
                final NetworkInterface iface = ifaces.nextElement();
                .info("Adding Allowed referers for Interface:" + iface.getDisplayName());
                final Enumeration<InetAddressias = iface.getInetAddresses();
                while(ias.hasMoreElements()){
                    final InetAddress ia = ias.nextElement();
                    final String address = ia.getHostAddress().trim().toLowerCase();
                    if ( ia instanceof Inet4Address ) {
                        referrers.add("http://" + address + ":0");
                        referrers.add("https://" + address + ":0");
                    }
                    if ( ia instanceof Inet6Address ) {
                        referrers.add("http://[" + address + "]" + ":0");
                        referrers.add("https://[" + address + "]" + ":0");
                    }
                }
            }
        } catch ( final SocketException se) {
            .error("Unable to detect network interfaces"se);
        }
        referrers.add("http://localhost" + ":0");
        referrers.add("http://127.0.0.1" + ":0");
        referrers.add("http://[::1]" + ":0");
        referrers.add("https://localhost" + ":0");
        referrers.add("https://127.0.0.1" + ":0");
        referrers.add("https://[::1]" + ":0");
        return referrers;
    }
    private void add(final List<URLurlsfinal String ref) {
        try {
            final URL u  = new URL(ref);
            urls.add(u);
        } catch (final MalformedURLException mue) {
            .warn("Unable to create URL from " + ref + " : " + mue.getMessage());
        }
    }

    
Create URLs out of the referrer list
    private URL[] createReferrerUrls(final Set<Stringreferrers) {
        final List<URLurls = new ArrayList<URL>();
        for(final String ref : referrers) {
            final int pos = ref.indexOf("://");
            // valid url?
            if ( pos != -1 ) {
                this.add(urlsref);
            } else {
                this.add(urls"http://" + ref + ":0");
                this.add(urls"https://" + ref + ":0");
            }
        }
        return urls.toArray(new URL[urls.size()]);
    }

    
Activate
    protected void activate(final ComponentContext ctx) {
        this. = PropertiesUtil.toBoolean(ctx.getProperties().get(), );
        String[] allowHosts = PropertiesUtil.toStringArray(ctx.getProperties().get());
        if ( allowHosts != null ) {
            if ( allowHosts.length == 0 ) {
                allowHosts = null;
            } else if ( allowHosts.length == 1 && allowHosts[0].trim().length() == 0 ) {
                allowHosts = null;
            }
        }
        final Set<StringallowedReferrers = this.getDefaultAllowedReferrers();
        if ( allowHosts != null ) {
            for(final String host : allowHosts) {
                allowedReferrers.add(host);
            }
        }
        this. = this.createReferrerUrls(allowedReferrers);
        this. = PropertiesUtil.toStringArray(ctx.getProperties().get());
        if ( this. != null && this..length == 1 && (this.[0] == null || this.[0].trim().length() == 0) ) {
            this. = null;
        }
        if ( this. != null ) {
            for(int i=0; i<.i++) {
                [i] = [i].toUpperCase();
            }
        }
        this. = registerConfigPrinter(ctx.getBundleContext());
    }
    protected void deactivate() {
        this..unregister();
    }
    private ServiceRegistration registerConfigPrinter(BundleContext bundleContext) {
        final ConfigurationPrinter cfgPrinter = new ConfigurationPrinter();
        final Dictionary<StringStringserviceProps = new Hashtable<StringString>();
        serviceProps.put(Constants.SERVICE_DESCRIPTION,
            "Apache Sling Referrer Filter Configuration Printer");
        serviceProps.put(Constants.SERVICE_VENDOR, "The Apache Software Foundation");
        serviceProps.put("felix.webconsole.label""slingreferrerfilter");
        serviceProps.put("felix.webconsole.title""Sling Referrer Filter");
        serviceProps.put("felix.webconsole.configprinter.modes""always");
       return bundleContext.registerService(Object.class.getName(),
                cfgPrinterserviceProps);
    }
    private boolean isModification(final HttpServletRequest req) {
        final String method = req.getMethod();
        if (  != null ) {
            for(final String m : ) {
                if ( m.equals(method) ) {
                    return true;
                }
            }
        }
        return false;
    }
    public void doFilter(final ServletRequest req,
                         final ServletResponse res,
                         final FilterChain chain)
    throws IOExceptionServletException {
        if ( req instanceof HttpServletRequest && res instanceof HttpServletResponse ) {
            final HttpServletRequest request = (HttpServletRequest)req;
            // is this a modification request from a browser
            if ( this.isBrowserRequest(request) && this.isModification(request) ) {
                if ( !this.isValidRequest(request) ) {
                    final HttpServletResponse response = (HttpServletResponse)res;
                    // we use 403
                    response.sendError(403);
                    return;
                }
            }
        }
        chain.doFilter(reqres);
    }
    final static class HostInfo {
        public String host;
        public String scheme;
        public int port;
    }
    HostInfo getHost(final String referrer) {
        final int startPos = referrer.indexOf("://") + 3;
        if ( startPos == 2 ) {
            // we consider this illegal
            return null;
        }
        final HostInfo info = new HostInfo();
        info.scheme = referrer.substring(0, startPos - 3);
        final int paramStart = referrer.indexOf('?');
        final String hostAndPath = (paramStart == -1 ? referrer : referrer.substring(0, paramStart));
        final int endPos = hostAndPath.indexOf('/'startPos);
        final String hostPart = (endPos == -1 ? hostAndPath.substring(startPos) : hostAndPath.substring(startPosendPos));
        final int hostNameStart = hostPart.indexOf('@') + 1;
        final int hostNameEnd = hostPart.lastIndexOf(':');
        if (hostNameEnd < hostNameStart ) {
            info.host = hostPart.substring(hostNameStart);
            if ( info.scheme.equals("http") ) {
                info.port = 80;
            } else if ( info.scheme.equals("https") ) {
                info.port = 443;
            }
        } else {
            info.host = hostPart.substring(hostNameStarthostNameEnd);
            info.port = Integer.valueOf(hostPart.substring(hostNameEnd + 1));
        }
        return info;
    }
    boolean isValidRequest(final HttpServletRequest request) {
        final String referrer = request.getHeader("referer");
        // check for missing/empty referrer
        if ( referrer == null || referrer.trim().length() == 0 ) {
            if ( !this. ) {
                this..info("Rejected empty referrer header for {} request to {}"request.getMethod(), request.getRequestURI());
            }
            return this.;
        }
        // check for relative referrer - which is always allowed
        if ( referrer.indexOf(":/") == - 1 ) {
            return true;
        }
        // check for air referrer - which is always allowed
        if ( referrer.startsWith("app:/") ) {
            return true;
        }
        final HostInfo info = getHost(referrer);
        if ( info == null ) {
            // if this is invalid we just return invalid
            this..info("Rejected illegal referrer header for {} request to {} : {}",
                    new Object[] {request.getMethod(), request.getRequestURI(), referrer});
            return false;
        }
        // allow the request if the host name of the referrer is
        // the same as the request's host name
        if ( info.host.equals(request.getServerName()) ) {
            return true;
        }
        boolean valid = false;
        for(final URL ref : this.) {
            if ( info.host.equals(ref.getHost()) && info.scheme.equals(ref.getProtocol()) ) {
                if ( ref.getPort() == 0 || info.port == ref.getPort() ) {
                    valid = true;
                    break;
                }
            }
        }
        if ( !valid) {
            this..info("Rejected referrer header for {} request to {} : {}",
                    new Object[] {request.getMethod(), request.getRequestURI(), referrer});
        }
        return valid;
    }

    

See also:
javax.servlet.Filter.init(javax.servlet.FilterConfig)
    public void init(final FilterConfig configthrows ServletException {
        // nothing to do
    }

    

See also:
javax.servlet.Filter.destroy()
    public void destroy() {
        // nothing to do
    }

    
Returns true if the given request can be assumed to be sent by a client browser such as Firefix, Internet Explorer, etc.

This method inspects the User-Agent header and returns true if the header contains the string Mozilla (known to be contained in Firefox, Internet Explorer, WebKit-based browsers User-Agent) or Opera (known to be contained in the Opera User-Agent).

Parameters:
request The request to inspect
Returns:
true if the request is assumed to be sent by a browser.
    private boolean isBrowserRequest(final HttpServletRequest request) {
        final String userAgent = request.getHeader();
        if (userAgent != null && (userAgent.contains() || userAgent.contains())) {
            return true;
        }
        return false;
    }
    public class ConfigurationPrinter {

        
Print out the allowedReferrers

See also:
org.apache.felix.webconsole.ConfigurationPrinter.printConfiguration(java.io.PrintWriter)
        public void printConfiguration(final PrintWriter pw) {
            pw.println("Current Apache Sling Referrer Filter Allowed Referrers:");
            pw.println();
            for (final URL url : ) {
                pw.println(url.toString());
            }
        }
    }
New to GrepCode? Check out our FAQ X