⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 urlsubtree.java

📁 一个完整的XACML工程,学习XACML技术的好例子!
💻 JAVA
字号:
/*
 * Copyright (c) 2000-2005, University of Salford
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice, this
 * list of conditions and the following disclaimer.
 *
 * Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the documentation
 * and/or other materials provided with the distribution.
 *
 * Neither the name of the University of Salford nor the names of its
 * contributors may be used to endorse or promote products derived from this
 * software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

package issrg.pba.rbac.policies;

import issrg.utils.ParsedURL;
import issrg.pba.rbac.BadURLException;
import issrg.pba.rbac.URLPrincipal;
import issrg.utils.repository.Entry;

import java.net.InetAddress;
import java.net.UnknownHostException;

/**
 * This Subtree implementation specifies a subtree of Entries identified by
 * URL. It uses a issrg.utils.ParsedURL utility class to decompose the URL
 * and identify the patterns in it, hence support for HTTP-like URLs.
 *
 * <p>The format of the URL is described in issrg.utils.ParsedURL. Note that 
 * the host name is either a valid DNS name, or an IP address, or "*"; the port
 * can be a number specifying a single port, or a range of ports specified as 
 * number "-" number.
 *
 * <p>To match the URLSubtree, the Entry must:
 * <ul>
 * <li>return a URLPrincipal as the result of getEntryName</li>
 * <li>have a protocol that matches the one specified in the Subtree (case of  
 * the characters is ignored)</li>
 * <li>either the Entry and the Subtree specification don't have the user name
 * specified, or they should match (case sensitive)</li>
 * <li>either the Entry and the Subtree specification don't have the password
 * specified, or they should match (case sensitive)</li>
 * <li>either the Entry has the same host name, as specified in the Subtree,
 * or it must be one of the IP addresses of the host specified in the Subtree,
 * or the Subtree host must be specified as "any host" wildcard - "*"</li>
 * <li>either the Entry has the same port number as the Subtree (the default 
 * one is used, if it is not specified explicitly), or the Entry's port must
 * match the range of ports specified in the Subtree, or the Subtree doesn't
 * have any port specified</li>
 * <li>the number of path components in the Entry must exceed the number of
 * path components in the Subtree by at least the minimum specified in the
 * Subtree (the paths are normalised prior to comparison, as explained below)</li>
 * <li>the number of path components in the Entry may exceed the number of
 * path components in the Subtree by no more than the maximum specified in the
 * Subtree (the paths are normalised prior to comparison, as explained below)</li>
 * <li>Entry must have path components matching all of the path components of 
 * the Subtree (case sensitive; the paths are normalised prior to comparison, 
 * as explained below)</li>
 * </ul>
 *
 * <p>During path normalisation all the "." and ".." (current directory and 
 * parent directory respectively) are dereferenced, as explained in 
 * issrg.utils.ParsedURL.
 */
public class URLSubtree implements Subtree {
    /**
     * Wildcard used in the policy to specify any host - so any host will be 
     * matched
     * as part of the URL subtree.
     */
    public static final String ANY_HOST="*";
    public static final String LOCALHOST="localhost";
    
    protected int defaultPort;
    protected int min;
    protected int max;
    protected int minPort;
    protected int maxPort;
    protected ParsedURL pu;
    protected Subtree [] exclude;
    
    protected String [] altIP = {}; // alternative IP addresses for the named host
    
    protected URLSubtree(){}
    
    /**
     * This constructor builds a URLSubtree, given a URL string (exceptions are
     * outlined below), a default port, the min and max levels from the base
     * directory.
     *
     * <p>The URL may contain a range of ports, not just one port. The range is
     * specified as nn-mm, where nn is the starting port number, and mm - the
     * ending port number. The subtree then matches any URLs with the port
     * matching any of the numbers between nn and mm, inclusive.
     *
     * <p>If the URL has the host specified by DNS name, then its IP addresses
     * will be looked up, so that the Entries will match the Subtree by either
     * of the IP addresses, or by the DNS name. If the host is specified as a
     * wildcard "*", Entries with any host will match.
     *
     * @param url is the URL string
     * @param defaultPort is the default port to assume for Entries with URLs 
     *    that do not specify any port
     * @param min is the minimum number of levels below the base URL that the
     *    Entry URL should be in; if the Entry is above this level, it doesn't 
     *    match this subtree
     * @param max is the maximum number of levels below the base URL that the
     *    Entry URL should be in; if the Entry is below this level, it doesn't 
     *    match this subtree
     *
     * @throws BadURLException, if the url string doesn't match the URL 
     *    specification
     *    (except for the port range bit), or the port numbers are not valid
     *    integers
     */
    public URLSubtree(String url, int defaultPort, int min, int max, Subtree [] exclude) throws BadURLException {
        Exception e=null;
        int minPort=-1; // unlimited
        int maxPort=-1; // unlimited
        pu = ParsedURL.parseURL(url); 
        
        String port;
        
        if (pu!=null && (port=pu.getPort())!=null){
            try{
                int j=port.indexOf('-');
                if (port.indexOf('-')<0) { // no range of ports has been specified
                    j=port.length();
                    port+="-"+port; // treat it as a range of ports: n <=> n-n
                }
                if (j>=port.length()-1) port+="65535"; // if no port is specified at the end, append the port
                
                minPort = Integer.parseInt(port.substring(0, j));
                maxPort = Integer.parseInt(port.substring(j+1)); // this shouldn't cause IndexOutOfBoundsException: port cannot be an empty string (it would be null then), so port+"-"+port doesn't end with a "-"
            } catch (NumberFormatException nfe) {
                e=nfe;
                pu=null;
            }
        }
        if (pu==null) throw new BadURLException("Malformed URL: "+url, e);
        
        if (!pu.getHost().equals(ANY_HOST)) {
            InetAddress [] hostAddresses = new InetAddress[0];
            InetAddress [] lhAddresses = new InetAddress[0];
            try{
                hostAddresses = InetAddress.getAllByName(pu.getHost());
            }catch (UnknownHostException uhe){
                // log that the host wasn't found
            }
            
            try{
                if (pu.getHost().compareToIgnoreCase(LOCALHOST)==0)
                    lhAddresses = InetAddress.getAllByName(InetAddress.getLocalHost().getHostName()); // if it is a "localhost", then look up other host names
            }catch (UnknownHostException uhe){
                // this shouldn't happen
            }
            // and their addresses
            altIP = new String[hostAddresses.length+lhAddresses.length];
            
            for (int i=0; i<hostAddresses.length; i++){
                altIP[i]=hostAddresses[i].getHostAddress();
            }
            
            for (int i=0; i<lhAddresses.length; i++){
                altIP[i+hostAddresses.length]=lhAddresses[i].getHostAddress();
            }
        }
        
        this.defaultPort=defaultPort;
        this.min=min;
        this.max=max;
        this.minPort=minPort;
        this.maxPort=maxPort;
        this.exclude=exclude;
    }
    
    /**
     * This method tests whether Entry e is part of this Subtree.
     *
     * @return true, if e's getEntryName returns a URLPrincipal 
     *   (e.g.&nbsp;URLEntry) and that URLPrincipal matches the Subtree, as
     *   explained above; false otherwise
     */
    public boolean contains(Entry e){
        URLPrincipal upi;
        if (!(e.getEntryName() instanceof URLPrincipal)) return false; // cannot compare non-URL entries
        
        upi=(URLPrincipal)e.getEntryName();
        
        int port = upi.getPort(); // it may be -1
        if (port<0) port=defaultPort; // assume the default port for this protocol, if port is not specified in the URL
        
        String [] up=upi.getPath(); // up and p now will be normalized paths
        String [] p=pu.getPath();
        
        //System.out.println("*** Matching subtrees: "+this+" and "+upi.getName()); //**********
        
        boolean result = upi.getProtocol().compareToIgnoreCase(pu.getProtocol())==0
                && (
                (upi.getUserName()!=null && pu.getUserName()!=null && upi.getUserName().equals(pu.getUserName()))
                || (upi.getUserName()==null && pu.getUserName()==null)
                )
                && (
                (upi.getPassword()!=null && pu.getPassword()!=null && upi.getPassword().equals(pu.getPassword()))
                || (upi.getPassword()==null && pu.getPassword()==null)
                )
                && port>=minPort && (port<=maxPort || maxPort<0) // I don't need to do the same for minPort, since any port number is greater than -1
                && (max<0 || up.length-p.length<=max) // up==upi.getPath(), p=pu.getPath() - the normalised paths of the URLs
                && up.length-p.length>=min // up should be longer than p - the difference should always be greater than 0
                ;
        
        if (result) {
            if (pu.getHost()!=null && upi.getHost()!=null) {
                if (!pu.getHost().equals(ANY_HOST)){
                    if (upi.getHost().compareToIgnoreCase(pu.getHost())!=0){ // look through the alternative IP addresses then
                        result=false;
                        
                        for (int i=0; !result && i<altIP.length; i++){ // loop until result==true or i>=altIP.length
                            result=altIP[i].equals(upi.getHost()); // the upi.getHost() should be an IP address then - match any of the IP addresses in the array
                        }
                    }
                }
            } else result=(upi.getHost()==null && pu.getHost()==null);
            
        }
        //System.out.println("\tURL matched criteria: "+result+"\n\tmatching paths now: "); //**********
        
        // ok, if all other criteria matched, match the paths; check that result is true before each iteration and stop comparing as soon as it becomes false
        for (int i=0; result && i<p.length; i++){ // i<up.length always - up is the same length, or longer than p
            result=up[i].equals(p[i]) || (i==p.length-1 && p[i].equals(".")); // if the path components are not equal (or it is the last component, and the subtree says to match the whole subdirectory), result=false, stop comparing
            //System.out.println("\t\tmatching: "+up[i]+"=="+p[i]+": "+result); //**********
        }
        
        //System.out.println("\tURL matched path: "+result+"\n\tmatching excludes now: "); //**********
        // ok, it matched the subtree; let's see if it matches any of the exclude statements
        if (exclude!=null){
            for (int i=0; result && i<exclude.length; i++){
                result=!exclude[i].contains(e);
            }
        }
        
        //System.out.println("\tresult: "+result); //**********
        return result;
    }
    
    public String toString(){
        String exclude=null;
        if (this.exclude!=null){
            exclude=", excluding [";
            for (int i=0; i<this.exclude.length; i++){
                exclude+=(i==0?"":", ")+this.exclude[i].toString();
            }
            exclude+="]";
        }
        
        return "URLSubtree with base URL="+pu.getNormalizedURL()+", min="+min+", max="+max+
                ", minPort="+minPort+", maxPort="+maxPort+", defaultPort="+defaultPort+
                ", protocol="+pu.getProtocol()+", user="+pu.getUserName()+
                ", password="+pu.getPassword()+", host="+pu.getHost()+
                ", path="+pu.getPathString()+
                (exclude==null?"":exclude);
    }

    public Object clone() {
        Subtree[] a = null;
        if (exclude != null) {
            a = new Subtree[exclude.length];
            System.arraycopy(exclude, 0, a, 0, a.length);
        }
        try {
            return new URLSubtree(pu.getURL(), defaultPort, min, max, a);
        } catch (issrg.pba.rbac.BadURLException bu) {
            bu.printStackTrace();
            return null;
        }
        
    }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -