Source Code Cross Referenced for SocketPermission.java in  » 6.0-JDK-Core » net » java » net » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Home
Java Source Code / Java Documentation
1.6.0 JDK Core
2.6.0 JDK Modules
3.6.0 JDK Modules com.sun
4.6.0 JDK Modules com.sun.java
5.6.0 JDK Modules sun
6.6.0 JDK Platform
7.Ajax
8.Apache Harmony Java SE
9.Aspect oriented
10.Authentication Authorization
11.Blogger System
12.Build
13.Byte Code
14.Cache
15.Chart
16.Chat
17.Code Analyzer
18.Collaboration
19.Content Management System
20.Database Client
21.Database DBMS
22.Database JDBC Connection Pool
23.Database ORM
24.Development
25.EJB Server
26.ERP CRM Financial
27.ESB
28.Forum
29.Game
30.GIS
31.Graphic 3D
32.Graphic Library
33.Groupware
34.HTML Parser
35.IDE
36.IDE Eclipse
37.IDE Netbeans
38.Installer
39.Internationalization Localization
40.Inversion of Control
41.Issue Tracking
42.J2EE
43.J2ME
44.JBoss
45.JMS
46.JMX
47.Library
48.Mail Clients
49.Music
50.Net
51.Parser
52.PDF
53.Portal
54.Profiler
55.Project Management
56.Report
57.RSS RDF
58.Rule Engine
59.Science
60.Scripting
61.Search Engine
62.Security
63.Sevlet Container
64.Source Control
65.Swing Library
66.Template Engine
67.Test Coverage
68.Testing
69.UML
70.Web Crawler
71.Web Framework
72.Web Mail
73.Web Server
74.Web Services
75.Web Services apache cxf 2.2.6
76.Web Services AXIS2
77.Wiki Engine
78.Workflow Engines
79.XML
80.XML UI
Java Source Code / Java Documentation » 6.0 JDK Core » net » java.net 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001        /*
0002         * Copyright 1997-2006 Sun Microsystems, Inc.  All Rights Reserved.
0003         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0004         *
0005         * This code is free software; you can redistribute it and/or modify it
0006         * under the terms of the GNU General Public License version 2 only, as
0007         * published by the Free Software Foundation.  Sun designates this
0008         * particular file as subject to the "Classpath" exception as provided
0009         * by Sun in the LICENSE file that accompanied this code.
0010         *
0011         * This code is distributed in the hope that it will be useful, but WITHOUT
0012         * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0013         * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
0014         * version 2 for more details (a copy is included in the LICENSE file that
0015         * accompanied this code).
0016         *
0017         * You should have received a copy of the GNU General Public License version
0018         * 2 along with this work; if not, write to the Free Software Foundation,
0019         * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0020         *
0021         * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
0022         * CA 95054 USA or visit www.sun.com if you need additional information or
0023         * have any questions.
0024         */
0025
0026        package java.net;
0027
0028        import java.util.Enumeration;
0029        import java.util.Vector;
0030        import java.util.List;
0031        import java.util.ArrayList;
0032        import java.util.Collections;
0033        import java.util.StringTokenizer;
0034        import java.net.InetAddress;
0035        import java.security.Permission;
0036        import java.security.PermissionCollection;
0037        import java.io.Serializable;
0038        import java.io.ObjectStreamField;
0039        import java.io.ObjectOutputStream;
0040        import java.io.ObjectInputStream;
0041        import java.io.IOException;
0042        import sun.net.util.IPAddressUtil;
0043        import sun.security.util.SecurityConstants;
0044
0045        /**
0046         * This class represents access to a network via sockets.
0047         * A SocketPermission consists of a 
0048         * host specification and a set of "actions" specifying ways to
0049         * connect to that host. The host is specified as
0050         * <pre>
0051         *    host = (hostname | IPv4address | iPv6reference) [:portrange]
0052         *    portrange = portnumber | -portnumber | portnumber-[portnumber]
0053         * </pre>
0054         * The host is expressed as a DNS name, as a numerical IP address,
0055         * or as "localhost" (for the local machine).
0056         * The wildcard "*" may be included once in a DNS name host
0057         * specification. If it is included, it must be in the leftmost 
0058         * position, as in "*.sun.com".
0059         * <p>
0060         * The format of the IPv6reference should follow that specified in <a
0061         * href="http://www.ietf.org/rfc/rfc2732.txt"><i>RFC&nbsp;2732: Format
0062         * for Literal IPv6 Addresses in URLs</i></a>:
0063         * <pre>
0064         *    ipv6reference = "[" IPv6address "]"
0065         *</pre>
0066         * For example, you can construct a SocketPermission instance
0067         * as the following:
0068         * <pre>
0069         *    String hostAddress = inetaddress.getHostAddress();
0070         *    if (inetaddress instanceof Inet6Address) {
0071         *        sp = new SocketPermission("[" + hostAddress + "]:" + port, action);
0072         *    } else {
0073         *        sp = new SocketPermission(hostAddress + ":" + port, action);
0074         *    }
0075         * </pre>
0076         * or
0077         * <pre>
0078         *    String host = url.getHost();
0079         *    sp = new SocketPermission(host + ":" + port, action);
0080         * </pre>
0081         * <p>
0082         * The <A HREF="Inet6Address.html#lform">full uncompressed form</A> of
0083         * an IPv6 literal address is also valid.
0084         * <p>
0085         * The port or portrange is optional. A port specification of the 
0086         * form "N-", where <i>N</i> is a port number, signifies all ports
0087         * numbered <i>N</i> and above, while a specification of the
0088         * form "-N" indicates all ports numbered <i>N</i> and below.
0089         * <p>
0090         * The possible ways to connect to the host are 
0091         * <pre>
0092         * accept
0093         * connect
0094         * listen
0095         * resolve
0096         * </pre>
0097         * The "listen" action is only meaningful when used with "localhost". 
0098         * The "resolve" action is implied when any of the other actions are present.
0099         * The action "resolve" refers to host/ip name service lookups.
0100         * 
0101         * <p>As an example of the creation and meaning of SocketPermissions,  
0102         * note that if the following permission:
0103         * 
0104         * <pre>
0105         *   p1 = new SocketPermission("puffin.eng.sun.com:7777", "connect,accept");
0106         * </pre>
0107         * 
0108         * is granted to some code, it allows that code to connect to port 7777 on
0109         * <code>puffin.eng.sun.com</code>, and to accept connections on that port.
0110         * 
0111         * <p>Similarly, if the following permission:
0112         * 
0113         * <pre>
0114         *   p1 = new SocketPermission("puffin.eng.sun.com:7777", "connect,accept");
0115         *   p2 = new SocketPermission("localhost:1024-", "accept,connect,listen");
0116         * </pre>
0117         * 
0118         * is granted to some code, it allows that code to 
0119         * accept connections on, connect to, or listen on any port between
0120         * 1024 and 65535 on the local host.
0121         *
0122         * <p>Note: Granting code permission to accept or make connections to remote
0123         * hosts may be dangerous because malevolent code can then more easily
0124         * transfer and share confidential data among parties who may not
0125         * otherwise have access to the data.
0126         * 
0127         * @see java.security.Permissions
0128         * @see SocketPermission
0129         *
0130         * @version 1.67 07/05/05
0131         *
0132         * @author Marianne Mueller
0133         * @author Roland Schemers 
0134         *
0135         * @serial exclude
0136         */
0137
0138        public final class SocketPermission extends Permission implements 
0139                java.io.Serializable {
0140            private static final long serialVersionUID = -7204263841984476862L;
0141
0142            /**
0143             * Connect to host:port
0144             */
0145            private final static int CONNECT = 0x1;
0146
0147            /**
0148             * Listen on host:port
0149             */
0150            private final static int LISTEN = 0x2;
0151
0152            /**
0153             * Accept a connection from host:port
0154             */
0155            private final static int ACCEPT = 0x4;
0156
0157            /**
0158             * Resolve DNS queries
0159             */
0160            private final static int RESOLVE = 0x8;
0161
0162            /**
0163             * No actions
0164             */
0165            private final static int NONE = 0x0;
0166
0167            /**
0168             * All actions
0169             */
0170            private final static int ALL = CONNECT | LISTEN | ACCEPT | RESOLVE;
0171
0172            // various port constants
0173            private static final int PORT_MIN = 0;
0174            private static final int PORT_MAX = 65535;
0175            private static final int PRIV_PORT_MAX = 1023;
0176
0177            // the actions mask
0178            private transient int mask;
0179
0180            /**
0181             * the actions string. 
0182             *
0183             * @serial
0184             */
0185
0186            private String actions; // Left null as long as possible, then
0187            // created and re-used in the getAction function.
0188
0189            // hostname part as it is passed
0190            private transient String hostname;
0191
0192            // the canonical name of the host
0193            // in the case of "*.foo.com", cname is ".foo.com".
0194
0195            private transient String cname;
0196
0197            // all the IP addresses of the host 
0198            private transient InetAddress[] addresses;
0199
0200            // true if the hostname is a wildcard (e.g. "*.sun.com")
0201            private transient boolean wildcard;
0202
0203            // true if we were initialized with a single numeric IP address
0204            private transient boolean init_with_ip;
0205
0206            // true if this SocketPermission represents an invalid/unknown host
0207            // used for implies when the delayed lookup has already failed
0208            private transient boolean invalid;
0209
0210            // port range on host
0211            private transient int[] portrange;
0212
0213            // true if the trustProxy system property is set
0214            private static boolean trustProxy;
0215
0216            static {
0217                Boolean tmp = (Boolean) java.security.AccessController
0218                        .doPrivileged(new sun.security.action.GetBooleanAction(
0219                                "trustProxy"));
0220                trustProxy = tmp.booleanValue();
0221            }
0222
0223            /**
0224             * Creates a new SocketPermission object with the specified actions.
0225             * The host is expressed as a DNS name, or as a numerical IP address.
0226             * Optionally, a port or a portrange may be supplied (separated
0227             * from the DNS name or IP address by a colon).
0228             * <p>
0229             * To specify the local machine, use "localhost" as the <i>host</i>.
0230             * Also note: An empty <i>host</i> String ("") is equivalent to "localhost".
0231             * <p>
0232             * The <i>actions</i> parameter contains a comma-separated list of the
0233             * actions granted for the specified host (and port(s)). Possible actions are
0234             * "connect", "listen", "accept", "resolve", or 
0235             * any combination of those. "resolve" is automatically added
0236             * when any of the other three are specified.
0237             * <p>
0238             * Examples of SocketPermission instantiation are the following: 
0239             * <pre>
0240             *    nr = new SocketPermission("www.catalog.com", "connect");
0241             *    nr = new SocketPermission("www.sun.com:80", "connect");
0242             *    nr = new SocketPermission("*.sun.com", "connect");
0243             *    nr = new SocketPermission("*.edu", "resolve");
0244             *    nr = new SocketPermission("204.160.241.0", "connect");
0245             *    nr = new SocketPermission("localhost:1024-65535", "listen");
0246             *    nr = new SocketPermission("204.160.241.0:1024-65535", "connect");
0247             * </pre>
0248             * 
0249             * @param host the hostname or IPaddress of the computer, optionally
0250             * including a colon followed by a port or port range. 
0251             * @param action the action string.
0252             */
0253            public SocketPermission(String host, String action) {
0254                super (getHost(host));
0255                // name initialized to getHost(host); NPE detected in getHost()
0256                init(getName(), getMask(action));
0257            }
0258
0259            SocketPermission(String host, int mask) {
0260                super (getHost(host));
0261                // name initialized to getHost(host); NPE detected in getHost()
0262                init(getName(), mask);
0263            }
0264
0265            private static String getHost(String host) {
0266                if (host.equals("")) {
0267                    return "localhost";
0268                } else {
0269                    /* IPv6 literal address used in this context should follow
0270                     * the format specified in RFC 2732;
0271                     * if not, we try to solve the unambiguous case
0272                     */
0273                    int ind;
0274                    if (host.charAt(0) != '[') {
0275                        if ((ind = host.indexOf(':')) != host.lastIndexOf(':')) {
0276                            /* More than one ":", meaning IPv6 address is not
0277                             * in RFC 2732 format;
0278                             * We will rectify user errors for all unambiguious cases
0279                             */
0280                            StringTokenizer st = new StringTokenizer(host, ":");
0281                            int tokens = st.countTokens();
0282                            if (tokens == 9) {
0283                                // IPv6 address followed by port
0284                                ind = host.lastIndexOf(':');
0285                                host = "[" + host.substring(0, ind) + "]"
0286                                        + host.substring(ind);
0287                            } else if (tokens == 8 && host.indexOf("::") == -1) {
0288                                // IPv6 address only, not followed by port
0289                                host = "[" + host + "]";
0290                            } else {
0291                                // could be ambiguous
0292                                throw new IllegalArgumentException("Ambiguous"
0293                                        + " hostport part");
0294                            }
0295                        }
0296                    }
0297                    return host;
0298                }
0299            }
0300
0301            private int[] parsePort(String port) throws Exception {
0302
0303                if (port == null || port.equals("") || port.equals("*")) {
0304                    return new int[] { PORT_MIN, PORT_MAX };
0305                }
0306
0307                int dash = port.indexOf('-');
0308
0309                if (dash == -1) {
0310                    int p = Integer.parseInt(port);
0311                    return new int[] { p, p };
0312                } else {
0313                    String low = port.substring(0, dash);
0314                    String high = port.substring(dash + 1);
0315                    int l, h;
0316
0317                    if (low.equals("")) {
0318                        l = PORT_MIN;
0319                    } else {
0320                        l = Integer.parseInt(low);
0321                    }
0322
0323                    if (high.equals("")) {
0324                        h = PORT_MAX;
0325                    } else {
0326                        h = Integer.parseInt(high);
0327                    }
0328                    if (l < 0 || h < 0 || h < l)
0329                        throw new IllegalArgumentException("invalid port range");
0330
0331                    return new int[] { l, h };
0332                }
0333            }
0334
0335            /**
0336             * Initialize the SocketPermission object. We don't do any DNS lookups
0337             * as this point, instead we hold off until the implies method is
0338             * called.
0339             */
0340            private void init(String host, int mask) {
0341                // Set the integer mask that represents the actions
0342
0343                if ((mask & ALL) != mask)
0344                    throw new IllegalArgumentException("invalid actions mask");
0345
0346                // always OR in RESOLVE if we allow any of the others
0347                this .mask = mask | RESOLVE;
0348
0349                // Parse the host name.  A name has up to three components, the
0350                // hostname, a port number, or two numbers representing a port
0351                // range.   "www.sun.com:8080-9090" is a valid host name. 
0352
0353                // With IPv6 an address can be 2010:836B:4179::836B:4179 
0354                // An IPv6 address needs to be enclose in [] 
0355                // For ex: [2010:836B:4179::836B:4179]:8080-9090 
0356                // Refer to RFC 2732 for more information. 
0357
0358                int rb = 0;
0359                int start = 0, end = 0;
0360                int sep = -1;
0361                String hostport = host;
0362                if (host.charAt(0) == '[') {
0363                    start = 1;
0364                    rb = host.indexOf(']');
0365                    if (rb != -1) {
0366                        host = host.substring(start, rb);
0367                    } else {
0368                        throw new IllegalArgumentException(
0369                                "invalid host/port: " + host);
0370                    }
0371                    sep = hostport.indexOf(':', rb + 1);
0372                } else {
0373                    start = 0;
0374                    sep = host.indexOf(':', rb);
0375                    end = sep;
0376                    if (sep != -1) {
0377                        host = host.substring(start, end);
0378                    }
0379                }
0380
0381                if (sep != -1) {
0382                    String port = hostport.substring(sep + 1);
0383                    try {
0384                        portrange = parsePort(port);
0385                    } catch (Exception e) {
0386                        throw new IllegalArgumentException(
0387                                "invalid port range: " + port);
0388                    }
0389                } else {
0390                    portrange = new int[] { PORT_MIN, PORT_MAX };
0391                }
0392
0393                hostname = host;
0394
0395                // is this a domain wildcard specification
0396                if (host.lastIndexOf('*') > 0) {
0397                    throw new IllegalArgumentException(
0398                            "invalid host wildcard specification");
0399                } else if (host.startsWith("*")) {
0400                    wildcard = true;
0401                    if (host.equals("*")) {
0402                        cname = "";
0403                    } else if (host.startsWith("*.")) {
0404                        cname = host.substring(1).toLowerCase();
0405                    } else {
0406                        throw new IllegalArgumentException(
0407                                "invalid host wildcard specification");
0408                    }
0409                    return;
0410                } else {
0411                    if (host.length() > 0) {
0412                        // see if we are being initialized with an IP address.
0413                        char ch = host.charAt(0);
0414                        if (ch == ':' || Character.digit(ch, 16) != -1) {
0415                            byte ip[] = IPAddressUtil
0416                                    .textToNumericFormatV4(host);
0417                            if (ip == null) {
0418                                ip = IPAddressUtil.textToNumericFormatV6(host);
0419                            }
0420                            if (ip != null) {
0421                                try {
0422                                    addresses = new InetAddress[] { InetAddress
0423                                            .getByAddress(ip) };
0424                                    init_with_ip = true;
0425                                } catch (UnknownHostException uhe) {
0426                                    // this shouldn't happen
0427                                    invalid = true;
0428                                }
0429                            }
0430                        }
0431                    }
0432                }
0433            }
0434
0435            /**
0436             * Convert an action string to an integer actions mask. 
0437             *
0438             * @param action the action string
0439             * @return the action mask
0440             */
0441            private static int getMask(String action) {
0442
0443                if (action == null) {
0444                    throw new NullPointerException("action can't be null");
0445                }
0446
0447                if (action.equals("")) {
0448                    throw new IllegalArgumentException("action can't be empty");
0449                }
0450
0451                int mask = NONE;
0452
0453                // Check against use of constants (used heavily within the JDK)
0454                if (action == SecurityConstants.SOCKET_RESOLVE_ACTION) {
0455                    return RESOLVE;
0456                } else if (action == SecurityConstants.SOCKET_CONNECT_ACTION) {
0457                    return CONNECT;
0458                } else if (action == SecurityConstants.SOCKET_LISTEN_ACTION) {
0459                    return LISTEN;
0460                } else if (action == SecurityConstants.SOCKET_ACCEPT_ACTION) {
0461                    return ACCEPT;
0462                } else if (action == SecurityConstants.SOCKET_CONNECT_ACCEPT_ACTION) {
0463                    return CONNECT | ACCEPT;
0464                }
0465
0466                char[] a = action.toCharArray();
0467
0468                int i = a.length - 1;
0469                if (i < 0)
0470                    return mask;
0471
0472                while (i != -1) {
0473                    char c;
0474
0475                    // skip whitespace
0476                    while ((i != -1)
0477                            && ((c = a[i]) == ' ' || c == '\r' || c == '\n'
0478                                    || c == '\f' || c == '\t'))
0479                        i--;
0480
0481                    // check for the known strings
0482                    int matchlen;
0483
0484                    if (i >= 6 && (a[i - 6] == 'c' || a[i - 6] == 'C')
0485                            && (a[i - 5] == 'o' || a[i - 5] == 'O')
0486                            && (a[i - 4] == 'n' || a[i - 4] == 'N')
0487                            && (a[i - 3] == 'n' || a[i - 3] == 'N')
0488                            && (a[i - 2] == 'e' || a[i - 2] == 'E')
0489                            && (a[i - 1] == 'c' || a[i - 1] == 'C')
0490                            && (a[i] == 't' || a[i] == 'T')) {
0491                        matchlen = 7;
0492                        mask |= CONNECT;
0493
0494                    } else if (i >= 6 && (a[i - 6] == 'r' || a[i - 6] == 'R')
0495                            && (a[i - 5] == 'e' || a[i - 5] == 'E')
0496                            && (a[i - 4] == 's' || a[i - 4] == 'S')
0497                            && (a[i - 3] == 'o' || a[i - 3] == 'O')
0498                            && (a[i - 2] == 'l' || a[i - 2] == 'L')
0499                            && (a[i - 1] == 'v' || a[i - 1] == 'V')
0500                            && (a[i] == 'e' || a[i] == 'E')) {
0501                        matchlen = 7;
0502                        mask |= RESOLVE;
0503
0504                    } else if (i >= 5 && (a[i - 5] == 'l' || a[i - 5] == 'L')
0505                            && (a[i - 4] == 'i' || a[i - 4] == 'I')
0506                            && (a[i - 3] == 's' || a[i - 3] == 'S')
0507                            && (a[i - 2] == 't' || a[i - 2] == 'T')
0508                            && (a[i - 1] == 'e' || a[i - 1] == 'E')
0509                            && (a[i] == 'n' || a[i] == 'N')) {
0510                        matchlen = 6;
0511                        mask |= LISTEN;
0512
0513                    } else if (i >= 5 && (a[i - 5] == 'a' || a[i - 5] == 'A')
0514                            && (a[i - 4] == 'c' || a[i - 4] == 'C')
0515                            && (a[i - 3] == 'c' || a[i - 3] == 'C')
0516                            && (a[i - 2] == 'e' || a[i - 2] == 'E')
0517                            && (a[i - 1] == 'p' || a[i - 1] == 'P')
0518                            && (a[i] == 't' || a[i] == 'T')) {
0519                        matchlen = 6;
0520                        mask |= ACCEPT;
0521
0522                    } else {
0523                        // parse error
0524                        throw new IllegalArgumentException(
0525                                "invalid permission: " + action);
0526                    }
0527
0528                    // make sure we didn't just match the tail of a word
0529                    // like "ackbarfaccept".  Also, skip to the comma.
0530                    boolean seencomma = false;
0531                    while (i >= matchlen && !seencomma) {
0532                        switch (a[i - matchlen]) {
0533                        case ',':
0534                            seencomma = true;
0535                            /*FALLTHROUGH*/
0536                        case ' ':
0537                        case '\r':
0538                        case '\n':
0539                        case '\f':
0540                        case '\t':
0541                            break;
0542                        default:
0543                            throw new IllegalArgumentException(
0544                                    "invalid permission: " + action);
0545                        }
0546                        i--;
0547                    }
0548
0549                    // point i at the location of the comma minus one (or -1).
0550                    i -= matchlen;
0551                }
0552
0553                return mask;
0554            }
0555
0556            /**
0557             * attempt to get the fully qualified domain name
0558             *
0559             */
0560            void getCanonName() throws UnknownHostException {
0561                if (cname != null || invalid)
0562                    return;
0563
0564                // attempt to get the canonical name
0565
0566                try {
0567                    // first get the IP addresses if we don't have them yet
0568                    // this is because we need the IP address to then get 
0569                    // FQDN.
0570                    if (addresses == null) {
0571                        getIP();
0572                    }
0573
0574                    // we have to do this check, otherwise we might not
0575                    // get the fully qualified domain name
0576                    if (init_with_ip) {
0577                        cname = addresses[0].getHostName(false).toLowerCase();
0578                    } else {
0579                        cname = InetAddress.getByName(
0580                                addresses[0].getHostAddress()).getHostName(
0581                                false).toLowerCase();
0582                    }
0583                } catch (UnknownHostException uhe) {
0584                    invalid = true;
0585                    throw uhe;
0586                }
0587            }
0588
0589            /**
0590             * get IP addresses. Sets invalid to true if we can't get them.
0591             *
0592             */
0593            void getIP() throws UnknownHostException {
0594                if (addresses != null || wildcard || invalid)
0595                    return;
0596
0597                try {
0598                    // now get all the IP addresses
0599                    String host;
0600                    if (getName().charAt(0) == '[') {
0601                        // Literal IPv6 address
0602                        host = getName().substring(1, getName().indexOf(']'));
0603                    } else {
0604                        int i = getName().indexOf(":");
0605                        if (i == -1)
0606                            host = getName();
0607                        else {
0608                            host = getName().substring(0, i);
0609                        }
0610                    }
0611
0612                    addresses = new InetAddress[] { InetAddress.getAllByName0(
0613                            host, false)[0] };
0614
0615                } catch (UnknownHostException uhe) {
0616                    invalid = true;
0617                    throw uhe;
0618                } catch (IndexOutOfBoundsException iobe) {
0619                    invalid = true;
0620                    throw new UnknownHostException(getName());
0621                }
0622            }
0623
0624            /**
0625             * Checks if this socket permission object "implies" the 
0626             * specified permission.
0627             * <P>
0628             * More specifically, this method first ensures that all of the following
0629             * are true (and returns false if any of them are not):<p>
0630             * <ul>
0631             * <li> <i>p</i> is an instanceof SocketPermission,<p>
0632             * <li> <i>p</i>'s actions are a proper subset of this
0633             * object's actions, and<p>
0634             * <li> <i>p</i>'s port range is included in this port range. Note:
0635             * port range is ignored when p only contains the action, 'resolve'.<p>
0636             * </ul>
0637             * 
0638             * Then <code>implies</code> checks each of the following, in order,
0639             * and for each returns true if the stated condition is true:<p>
0640             * <ul>
0641             * <li> If this object was initialized with a single IP address and one of <i>p</i>'s 
0642             * IP addresses is equal to this object's IP address.<p>
0643             * <li>If this object is a wildcard domain (such as *.sun.com), and
0644             * <i>p</i>'s canonical name (the name without any preceding *)
0645             * ends with this object's canonical host name. For example, *.sun.com
0646             * implies *.eng.sun.com..<p>
0647             * <li>If this object was not initialized with a single IP address, and one of this
0648             * object's IP addresses equals one of <i>p</i>'s IP addresses.<p>
0649             * <li>If this canonical name equals <i>p</i>'s canonical name.<p>
0650             * </ul>
0651             * 
0652             * If none of the above are true, <code>implies</code> returns false.
0653             * @param p the permission to check against.
0654             *
0655             * @return true if the specified permission is implied by this object,
0656             * false if not.  
0657             */
0658
0659            public boolean implies(Permission p) {
0660                int i, j;
0661
0662                if (!(p instanceof  SocketPermission))
0663                    return false;
0664
0665                if (p == this )
0666                    return true;
0667
0668                SocketPermission that = (SocketPermission) p;
0669
0670                return ((this .mask & that.mask) == that.mask)
0671                        && impliesIgnoreMask(that);
0672            }
0673
0674            /**
0675             * Checks if the incoming Permission's action are a proper subset of
0676             * the this object's actions.
0677             * <P>
0678             * Check, in the following order:
0679             * <ul>
0680             * <li> Checks that "p" is an instanceof a SocketPermission
0681             * <li> Checks that "p"'s actions are a proper subset of the
0682             * current object's actions.
0683             * <li> Checks that "p"'s port range is included in this port range
0684             * <li> If this object was initialized with an IP address, checks that 
0685             *      one of "p"'s IP addresses is equal to this object's IP address.
0686             * <li> If either object is a wildcard domain (i.e., "*.sun.com"),
0687             *      attempt to match based on the wildcard.
0688             * <li> If this object was not initialized with an IP address, attempt
0689             *      to find a match based on the IP addresses in both objects.
0690             * <li> Attempt to match on the canonical hostnames of both objects.
0691             * </ul>
0692             * @param p the incoming permission request
0693             *
0694             * @return true if "permission" is a proper subset of the current object,
0695             * false if not.  
0696             */
0697
0698            boolean impliesIgnoreMask(SocketPermission that) {
0699                int i, j;
0700
0701                if ((that.mask & RESOLVE) != that.mask) {
0702                    // check port range
0703                    if ((that.portrange[0] < this .portrange[0])
0704                            || (that.portrange[1] > this .portrange[1])) {
0705                        return false;
0706                    }
0707                }
0708
0709                // allow a "*" wildcard to always match anything
0710                if (this .wildcard && "".equals(this .cname))
0711                    return true;
0712
0713                // return if either one of these NetPerm objects are invalid...
0714                if (this .invalid || that.invalid) {
0715                    return (trustProxy ? inProxyWeTrust(that) : false);
0716                }
0717
0718                if (this .getName().equalsIgnoreCase(that.getName())) {
0719                    return true;
0720                }
0721
0722                try {
0723                    if (this .init_with_ip) { // we only check IP addresses
0724                        if (that.wildcard)
0725                            return false;
0726
0727                        if (that.init_with_ip) {
0728                            return (this .addresses[0].equals(that.addresses[0]));
0729                        } else {
0730                            if (that.addresses == null) {
0731                                that.getIP();
0732                            }
0733                            for (i = 0; i < that.addresses.length; i++) {
0734                                if (this .addresses[0].equals(that.addresses[i]))
0735                                    return true;
0736                            }
0737                        }
0738                        // since "this" was initialized with an IP address, we
0739                        // don't check any other cases
0740                        return false;
0741                    }
0742
0743                    // check and see if we have any wildcards...
0744                    if (this .wildcard || that.wildcard) {
0745                        // if they are both wildcards, return true iff
0746                        // that's cname ends with this cname (i.e., *.sun.com
0747                        // implies *.eng.sun.com)
0748                        if (this .wildcard && that.wildcard)
0749                            return (that.cname.endsWith(this .cname));
0750
0751                        // a non-wildcard can't imply a wildcard
0752                        if (that.wildcard)
0753                            return false;
0754
0755                        // this is a wildcard, lets see if that's cname ends with
0756                        // it...
0757                        if (that.cname == null) {
0758                            that.getCanonName();
0759                        }
0760                        return (that.cname.endsWith(this .cname));
0761                    }
0762
0763                    // comapare IP addresses
0764                    if (this .addresses == null) {
0765                        this .getIP();
0766                    }
0767
0768                    if (that.addresses == null) {
0769                        that.getIP();
0770                    }
0771
0772                    for (j = 0; j < this .addresses.length; j++) {
0773                        for (i = 0; i < that.addresses.length; i++) {
0774                            if (this .addresses[j].equals(that.addresses[i]))
0775                                return true;
0776                        }
0777                    }
0778
0779                    // XXX: if all else fails, compare hostnames?
0780                    // Do we really want this?
0781                    if (this .cname == null) {
0782                        this .getCanonName();
0783                    }
0784
0785                    if (that.cname == null) {
0786                        that.getCanonName();
0787                    }
0788
0789                    return (this .cname.equalsIgnoreCase(that.cname));
0790
0791                } catch (UnknownHostException uhe) {
0792                    if (trustProxy)
0793                        return inProxyWeTrust(that);
0794                }
0795
0796                // make sure the first thing that is done here is to return
0797                // false. If not, uncomment the return false in the above catch.
0798
0799                return false;
0800            }
0801
0802            private boolean inProxyWeTrust(SocketPermission that) {
0803                // if we trust the proxy, we see if the original names/IPs passed
0804                // in were equal.
0805
0806                String this Host = hostname;
0807                String thatHost = that.hostname;
0808
0809                if (this Host == null)
0810                    return false;
0811                else
0812                    return this Host.equalsIgnoreCase(thatHost);
0813
0814            }
0815
0816            /**
0817             * Checks two SocketPermission objects for equality. 
0818             * <P>
0819             * @param obj the object to test for equality with this object.
0820             * 
0821             * @return true if <i>obj</i> is a SocketPermission, and has the
0822             *  same hostname, port range, and actions as this
0823             *  SocketPermission object. However, port range will be ignored
0824             *  in the comparison if <i>obj</i> only contains the action, 'resolve'.
0825             */
0826            public boolean equals(Object obj) {
0827                if (obj == this )
0828                    return true;
0829
0830                if (!(obj instanceof  SocketPermission))
0831                    return false;
0832
0833                SocketPermission that = (SocketPermission) obj;
0834
0835                //this is (overly?) complex!!!
0836
0837                // check the mask first
0838                if (this .mask != that.mask)
0839                    return false;
0840
0841                if ((that.mask & RESOLVE) != that.mask) {
0842                    // now check the port range...
0843                    if ((this .portrange[0] != that.portrange[0])
0844                            || (this .portrange[1] != that.portrange[1])) {
0845                        return false;
0846                    }
0847                }
0848
0849                // short cut. This catches:
0850                //  "crypto" equal to "crypto", or
0851                // "1.2.3.4" equal to "1.2.3.4.", or 
0852                //  "*.edu" equal to "*.edu", but it 
0853                //  does not catch "crypto" equal to
0854                // "crypto.eng.sun.com".
0855
0856                if (this .getName().equalsIgnoreCase(that.getName())) {
0857                    return true;
0858                }
0859
0860                // we now attempt to get the Canonical (FQDN) name and
0861                // compare that. If this fails, about all we can do is return
0862                // false.
0863
0864                try {
0865                    this .getCanonName();
0866                    that.getCanonName();
0867                } catch (UnknownHostException uhe) {
0868                    return false;
0869                }
0870
0871                if (this .invalid || that.invalid)
0872                    return false;
0873
0874                if (this .cname != null) {
0875                    return this .cname.equalsIgnoreCase(that.cname);
0876                }
0877
0878                return false;
0879            }
0880
0881            /**
0882             * Returns the hash code value for this object.
0883             *
0884             * @return a hash code value for this object.
0885             */
0886
0887            public int hashCode() {
0888                /*
0889                 * If this SocketPermission was initialized with an IP address
0890                 * or a wildcard, use getName().hashCode(), otherwise use
0891                 * the hashCode() of the host name returned from 
0892                 * java.net.InetAddress.getHostName method.
0893                 */
0894
0895                if (init_with_ip || wildcard) {
0896                    return this .getName().hashCode();
0897                }
0898
0899                try {
0900                    getCanonName();
0901                } catch (UnknownHostException uhe) {
0902
0903                }
0904
0905                if (invalid || cname == null)
0906                    return this .getName().hashCode();
0907                else
0908                    return this .cname.hashCode();
0909            }
0910
0911            /**
0912             * Return the current action mask.
0913             *
0914             * @return the actions mask.
0915             */
0916
0917            int getMask() {
0918                return mask;
0919            }
0920
0921            /**
0922             * Returns the "canonical string representation" of the actions in the
0923             * specified mask.
0924             * Always returns present actions in the following order: 
0925             * connect, listen, accept, resolve.  
0926             *
0927             * @param mask a specific integer action mask to translate into a string
0928             * @return the canonical string representation of the actions
0929             */
0930            private static String getActions(int mask) {
0931                StringBuilder sb = new StringBuilder();
0932                boolean comma = false;
0933
0934                if ((mask & CONNECT) == CONNECT) {
0935                    comma = true;
0936                    sb.append("connect");
0937                }
0938
0939                if ((mask & LISTEN) == LISTEN) {
0940                    if (comma)
0941                        sb.append(',');
0942                    else
0943                        comma = true;
0944                    sb.append("listen");
0945                }
0946
0947                if ((mask & ACCEPT) == ACCEPT) {
0948                    if (comma)
0949                        sb.append(',');
0950                    else
0951                        comma = true;
0952                    sb.append("accept");
0953                }
0954
0955                if ((mask & RESOLVE) == RESOLVE) {
0956                    if (comma)
0957                        sb.append(',');
0958                    else
0959                        comma = true;
0960                    sb.append("resolve");
0961                }
0962
0963                return sb.toString();
0964            }
0965
0966            /**
0967             * Returns the canonical string representation of the actions.
0968             * Always returns present actions in the following order: 
0969             * connect, listen, accept, resolve.  
0970             *
0971             * @return the canonical string representation of the actions.
0972             */
0973            public String getActions() {
0974                if (actions == null)
0975                    actions = getActions(this .mask);
0976
0977                return actions;
0978            }
0979
0980            /**
0981             * Returns a new PermissionCollection object for storing SocketPermission 
0982             * objects.
0983             * <p>
0984             * SocketPermission objects must be stored in a manner that allows them 
0985             * to be inserted into the collection in any order, but that also enables the 
0986             * PermissionCollection <code>implies</code>
0987             * method to be implemented in an efficient (and consistent) manner.
0988             *
0989             * @return a new PermissionCollection object suitable for storing SocketPermissions.
0990             */
0991
0992            public PermissionCollection newPermissionCollection() {
0993                return new SocketPermissionCollection();
0994            }
0995
0996            /**
0997             * WriteObject is called to save the state of the SocketPermission 
0998             * to a stream. The actions are serialized, and the superclass
0999             * takes care of the name.
1000             */
1001            private synchronized void writeObject(java.io.ObjectOutputStream s)
1002                    throws IOException {
1003                // Write out the actions. The superclass takes care of the name
1004                // call getActions to make sure actions field is initialized
1005                if (actions == null)
1006                    getActions();
1007                s.defaultWriteObject();
1008            }
1009
1010            /**
1011             * readObject is called to restore the state of the SocketPermission from
1012             * a stream.
1013             */
1014            private synchronized void readObject(java.io.ObjectInputStream s)
1015                    throws IOException, ClassNotFoundException {
1016                // Read in the action, then initialize the rest
1017                s.defaultReadObject();
1018                init(getName(), getMask(actions));
1019            }
1020
1021            /*
1022            public String toString() 
1023            {
1024            StringBuffer s = new StringBuffer(super.toString() + "\n" +
1025                "cname = " + cname + "\n" +
1026                "wildcard = " + wildcard + "\n" +
1027                "invalid = " + invalid + "\n" +
1028            	    "portrange = " + portrange[0] + "," + portrange[1] + "\n");
1029            if (addresses != null) for (int i=0; i<addresses.length; i++) {
1030                s.append( addresses[i].getHostAddress());
1031                s.append("\n");
1032            } else {
1033                s.append("(no addresses)\n");
1034            }
1035
1036            return s.toString();
1037            }
1038
1039            public static void main(String args[]) throws Exception {
1040            SocketPermission this_ = new SocketPermission(args[0], "connect");
1041            SocketPermission that_ = new SocketPermission(args[1], "connect");
1042            System.out.println("-----\n");
1043            System.out.println("this.implies(that) = " + this_.implies(that_));
1044            System.out.println("-----\n");
1045            System.out.println("this = "+this_);
1046            System.out.println("-----\n");
1047            System.out.println("that = "+that_);
1048            System.out.println("-----\n");
1049
1050            SocketPermissionCollection nps = new SocketPermissionCollection();
1051            nps.add(this_);
1052            nps.add(new SocketPermission("www-leland.stanford.edu","connect"));
1053            nps.add(new SocketPermission("www-sun.com","connect"));
1054            System.out.println("nps.implies(that) = " + nps.implies(that_));
1055            System.out.println("-----\n");
1056            }
1057             */
1058        }
1059
1060        /**
1061
1062         if (init'd with IP, key is IP as string)
1063         if wildcard, its the wild card
1064         else its the cname?
1065
1066         *
1067         * @see java.security.Permission
1068         * @see java.security.Permissions
1069         * @see java.security.PermissionCollection
1070         *
1071         * @version 1.67 05/05/07
1072         *
1073         * @author Roland Schemers
1074         *
1075         * @serial include
1076         */
1077
1078        final class SocketPermissionCollection extends PermissionCollection
1079                implements  Serializable {
1080            // Not serialized; see serialization section at end of class
1081            private transient List perms;
1082
1083            /**
1084             * Create an empty SocketPermissions object.
1085             *
1086             */
1087
1088            public SocketPermissionCollection() {
1089                perms = new ArrayList();
1090            }
1091
1092            /**
1093             * Adds a permission to the SocketPermissions. The key for the hash is
1094             * the name in the case of wildcards, or all the IP addresses.
1095             *
1096             * @param permission the Permission object to add.
1097             *
1098             * @exception IllegalArgumentException - if the permission is not a
1099             *                                       SocketPermission
1100             *
1101             * @exception SecurityException - if this SocketPermissionCollection object
1102             *                                has been marked readonly
1103             */
1104
1105            public void add(Permission permission) {
1106                if (!(permission instanceof  SocketPermission))
1107                    throw new IllegalArgumentException("invalid permission: "
1108                            + permission);
1109                if (isReadOnly())
1110                    throw new SecurityException(
1111                            "attempt to add a Permission to a readonly PermissionCollection");
1112
1113                // optimization to ensure perms most likely to be tested
1114                // show up early (4301064)
1115                synchronized (this ) {
1116                    perms.add(0, permission);
1117                }
1118            }
1119
1120            /**
1121             * Check and see if this collection of permissions implies the permissions 
1122             * expressed in "permission".
1123             *
1124             * @param p the Permission object to compare
1125             *
1126             * @return true if "permission" is a proper subset of a permission in 
1127             * the collection, false if not.
1128             */
1129
1130            public boolean implies(Permission permission) {
1131                if (!(permission instanceof  SocketPermission))
1132                    return false;
1133
1134                SocketPermission np = (SocketPermission) permission;
1135
1136                int desired = np.getMask();
1137                int effective = 0;
1138                int needed = desired;
1139
1140                synchronized (this ) {
1141                    int len = perms.size();
1142                    //System.out.println("implies "+np);
1143                    for (int i = 0; i < len; i++) {
1144                        SocketPermission x = (SocketPermission) perms.get(i);
1145                        //System.out.println("  trying "+x);
1146                        if (((needed & x.getMask()) != 0)
1147                                && x.impliesIgnoreMask(np)) {
1148                            effective |= x.getMask();
1149                            if ((effective & desired) == desired)
1150                                return true;
1151                            needed = (desired ^ effective);
1152                        }
1153                    }
1154                }
1155                return false;
1156            }
1157
1158            /**
1159             * Returns an enumeration of all the SocketPermission objects in the 
1160             * container.
1161             *
1162             * @return an enumeration of all the SocketPermission objects.
1163             */
1164
1165            public Enumeration elements() {
1166                // Convert Iterator into Enumeration
1167                synchronized (this ) {
1168                    return Collections.enumeration(perms);
1169                }
1170            }
1171
1172            private static final long serialVersionUID = 2787186408602843674L;
1173
1174            // Need to maintain serialization interoperability with earlier releases,
1175            // which had the serializable field:
1176
1177            // 
1178            // The SocketPermissions for this set.
1179            // @serial
1180            // 
1181            // private Vector permissions;
1182
1183            /**
1184             * @serialField permissions java.util.Vector
1185             *     A list of the SocketPermissions for this set.
1186             */
1187            private static final ObjectStreamField[] serialPersistentFields = { new ObjectStreamField(
1188                    "permissions", Vector.class), };
1189
1190            /**
1191             * @serialData "permissions" field (a Vector containing the SocketPermissions).
1192             */
1193            /*
1194             * Writes the contents of the perms field out as a Vector for
1195             * serialization compatibility with earlier releases.
1196             */
1197            private void writeObject(ObjectOutputStream out) throws IOException {
1198                // Don't call out.defaultWriteObject()
1199
1200                // Write out Vector
1201                Vector permissions = new Vector(perms.size());
1202
1203                synchronized (this ) {
1204                    permissions.addAll(perms);
1205                }
1206
1207                ObjectOutputStream.PutField pfields = out.putFields();
1208                pfields.put("permissions", permissions);
1209                out.writeFields();
1210            }
1211
1212            /*
1213             * Reads in a Vector of SocketPermissions and saves them in the perms field.
1214             */
1215            private void readObject(ObjectInputStream in) throws IOException,
1216                    ClassNotFoundException {
1217                // Don't call in.defaultReadObject()
1218
1219                // Read in serialized fields
1220                ObjectInputStream.GetField gfields = in.readFields();
1221
1222                // Get the one we want
1223                Vector permissions = (Vector) gfields.get("permissions", null);
1224                perms = new ArrayList(permissions.size());
1225                perms.addAll(permissions);
1226            }
1227        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.