1237 lines · 39.9 KB · Java
RawDownload
/* * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation.  Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code 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 General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package sun.security.provider; import java.io.*;import java.lang.RuntimePermission;import java.net.SocketPermission;import java.net.URL;import java.util.Enumeration;import java.util.Hashtable;import java.util.LinkedList;import java.util.ListIterator;import java.util.Vector;import java.util.StringTokenizer;import java.text.MessageFormat;import javax.security.auth.x500.X500Principal; import java.security.GeneralSecurityException;import sun.security.util.Debug;import sun.security.util.PropertyExpander;import sun.security.util.ResourcesMgr; /** * The policy for a Java runtime (specifying * which permissions are available for code from various principals) * is represented as a separate * persistent configuration.  The configuration may be stored as a * flat ASCII file, as a serialized binary file of * the Policy class, or as a database. <p> * * <p>The Java runtime creates one global Policy object, which is used to * represent the static policy configuration file.  It is consulted by * a ProtectionDomain when the protection domain initializes its set of * permissions. <p> * * <p>The Policy <code>init</code> method parses the policy * configuration file, and then * populates the Policy object.  The Policy object is agnostic in that * it is not involved in making policy decisions.  It is merely the * Java runtime representation of the persistent policy configuration * file. <p> * * <p>When a protection domain needs to initialize its set of * permissions, it executes code such as the following * to ask the global Policy object to populate a * Permissions object with the appropriate permissions: * <pre> *  policy = Policy.getPolicy(); *  Permissions perms = policy.getPermissions(protectiondomain) * </pre> * * <p>The protection domain contains CodeSource * object, which encapsulates its codebase (URL) and public key attributes. * It also contains the principals associated with the domain. * The Policy object evaluates the global policy in light of who the * principal is and what the code source is and returns an appropriate * Permissions object. * * @author Roland Schemers * @author Ram Marti * * @since 1.2 */ public class PolicyParser {     // needs to be public for PolicyTool    public static final String REPLACE_NAME = "PolicyParser.REPLACE_NAME";     private static final String EXTDIRS_PROPERTY = "java.ext.dirs";    private static final String OLD_EXTDIRS_EXPANSION =        "${" + EXTDIRS_PROPERTY + "}";     // package-private: used by PolicyFile for static policy    static final String EXTDIRS_EXPANSION = "${{" + EXTDIRS_PROPERTY + "}}";      private Vector<GrantEntry> grantEntries;     // Convenience variables for parsing    private static final Debug debug = Debug.getInstance("parser",                                                "\t[Policy Parser]");    private StreamTokenizer st;    private int lookahead;    private boolean expandProp = false;    private String keyStoreUrlString = null; // unexpanded    private String keyStoreType = null;    private String keyStoreProvider = null;    private String storePassURL = null;     private String expand(String value)        throws PropertyExpander.ExpandException    {        return expand(value, false);    }     private String expand(String value, boolean encodeURL)        throws PropertyExpander.ExpandException    {        if (!expandProp) {            return value;        } else {            return PropertyExpander.expand(value, encodeURL);        }    }     /**     * Creates a PolicyParser object.     */     public PolicyParser() {        grantEntries = new Vector<GrantEntry>();    }      public PolicyParser(boolean expandProp) {        this();        this.expandProp = expandProp;    }     /**     * Reads a policy configuration into the Policy object using a     * Reader object. <p>     *     * @param policy the policy Reader object.     *     * @exception ParsingException if the policy configuration contains     *          a syntax error.     *     * @exception IOException if an error occurs while reading the policy     *          configuration.     */     public void read(Reader policy)        throws ParsingException, IOException    {        if (!(policy instanceof BufferedReader)) {            policy = new BufferedReader(policy);        }         /**         * Configure the stream tokenizer:         *      Recognize strings between "..."         *      Don't convert words to lowercase         *      Recognize both C-style and C++-style comments         *      Treat end-of-line as white space, not as a token         */        st   = new StreamTokenizer(policy);         st.resetSyntax();        st.wordChars('a', 'z');        st.wordChars('A', 'Z');        st.wordChars('.', '.');        st.wordChars('0', '9');        st.wordChars('_', '_');        st.wordChars('$', '$');        st.wordChars(128 + 32, 255);        st.whitespaceChars(0, ' ');        st.commentChar('/');        st.quoteChar('\'');        st.quoteChar('"');        st.lowerCaseMode(false);        st.ordinaryChar('/');        st.slashSlashComments(true);        st.slashStarComments(true);         /**         * The main parsing loop.  The loop is executed once         * for each entry in the config file.      The entries         * are delimited by semicolons.   Once we've read in         * the information for an entry, go ahead and try to         * add it to the policy vector.         *         */         lookahead = st.nextToken();        while (lookahead != StreamTokenizer.TT_EOF) {            if (peek("grant")) {                GrantEntry ge = parseGrantEntry();                // could be null if we couldn't expand a property                if (ge != null)                    add(ge);            } else if (peek("keystore") && keyStoreUrlString==null) {                // only one keystore entry per policy file, others will be                // ignored                parseKeyStoreEntry();            } else if (peek("keystorePasswordURL") && storePassURL==null) {                // only one keystore passwordURL per policy file, others will be                // ignored                parseStorePassURL();            } else {                // error?            }            match(";");        }         if (keyStoreUrlString == null && storePassURL != null) {            throw new ParsingException(ResourcesMgr.getString                ("keystorePasswordURL.can.not.be.specified.without.also.specifying.keystore"));        }    }     public void add(GrantEntry ge)    {        grantEntries.addElement(ge);    }     public void replace(GrantEntry origGe, GrantEntry newGe)    {        grantEntries.setElementAt(newGe, grantEntries.indexOf(origGe));    }     public boolean remove(GrantEntry ge)    {        return grantEntries.removeElement(ge);    }     /**     * Returns the (possibly expanded) keystore location, or null if the     * expansion fails.     */    public String getKeyStoreUrl() {        try {            if (keyStoreUrlString!=null && keyStoreUrlString.length()!=0) {                return expand(keyStoreUrlString, true).replace                                                (File.separatorChar, '/');            }        } catch (PropertyExpander.ExpandException peee) {            if (debug != null) {                debug.println(peee.toString());            }            return null;        }        return null;    }     public void setKeyStoreUrl(String url) {        keyStoreUrlString = url;    }     public String getKeyStoreType() {        return keyStoreType;    }     public void setKeyStoreType(String type) {        keyStoreType = type;    }     public String getKeyStoreProvider() {        return keyStoreProvider;    }     public void setKeyStoreProvider(String provider) {        keyStoreProvider = provider;    }     public String getStorePassURL() {        try {            if (storePassURL!=null && storePassURL.length()!=0) {                return expand(storePassURL, true).replace                                                (File.separatorChar, '/');            }        } catch (PropertyExpander.ExpandException peee) {            if (debug != null) {                debug.println(peee.toString());            }            return null;        }        return null;    }     public void setStorePassURL(String storePassURL) {        this.storePassURL = storePassURL;    }     /**     * Enumerate all the entries in the global policy object.     * This method is used by policy admin tools.   The tools     * should use the Enumeration methods on the returned object     * to fetch the elements sequentially.     */    public Enumeration<GrantEntry> grantElements(){        return grantEntries.elements();    }     /**     * write out the policy     */     public void write(Writer policy)    {        PrintWriter out = new PrintWriter(new BufferedWriter(policy));         Enumeration<GrantEntry> enum_ = grantElements();         out.println("/* AUTOMATICALLY GENERATED ON "+                    (new java.util.Date()) + "*/");        out.println("/* DO NOT EDIT */");        out.println();         // write the (unexpanded) keystore entry as the first entry of the        // policy file        if (keyStoreUrlString != null) {            writeKeyStoreEntry(out);        }        if (storePassURL != null) {            writeStorePassURL(out);        }         // write "grant" entries        while (enum_.hasMoreElements()) {            GrantEntry ge = enum_.nextElement();            ge.write(out);            out.println();        }        out.flush();    }     /**     * parses a keystore entry     */    private void parseKeyStoreEntry() throws ParsingException, IOException {        match("keystore");        keyStoreUrlString = match("quoted string");         // parse keystore type        if (!peek(",")) {            return; // default type        }        match(",");         if (peek("\"")) {            keyStoreType = match("quoted string");        } else {            throw new ParsingException(st.lineno(),                        ResourcesMgr.getString("expected.keystore.type"));        }         // parse keystore provider        if (!peek(",")) {            return; // provider optional        }        match(",");         if (peek("\"")) {            keyStoreProvider = match("quoted string");        } else {            throw new ParsingException(st.lineno(),                        ResourcesMgr.getString("expected.keystore.provider"));        }    }     private void parseStorePassURL() throws ParsingException, IOException {        match("keyStorePasswordURL");        storePassURL = match("quoted string");    }     /**     * writes the (unexpanded) keystore entry     */    private void writeKeyStoreEntry(PrintWriter out) {        out.print("keystore \"");        out.print(keyStoreUrlString);        out.print('"');        if (keyStoreType != null && keyStoreType.length() > 0)            out.print(", \"" + keyStoreType + "\"");        if (keyStoreProvider != null && keyStoreProvider.length() > 0)            out.print(", \"" + keyStoreProvider + "\"");        out.println(";");        out.println();    }     private void writeStorePassURL(PrintWriter out) {        out.print("keystorePasswordURL \"");        out.print(storePassURL);        out.print('"');        out.println(";");        out.println();    }     /**     * parse a Grant entry     */    private GrantEntry parseGrantEntry()        throws ParsingException, IOException    {        GrantEntry e = new GrantEntry();        LinkedList<PrincipalEntry> principals = null;        boolean ignoreEntry = false;         match("grant");         while(!peek("{")) {             if (peekAndMatch("Codebase")) {                if (e.codeBase != null)                    throw new ParsingException(                            st.lineno(),                            ResourcesMgr.getString                                ("multiple.Codebase.expressions"));                e.codeBase = match("quoted string");                peekAndMatch(",");            } else if (peekAndMatch("SignedBy")) {                if (e.signedBy != null)                    throw new ParsingException(                            st.lineno(),                            ResourcesMgr.getString(                                "multiple.SignedBy.expressions"));                e.signedBy = match("quoted string");                 // verify syntax of the aliases                StringTokenizer aliases = new StringTokenizer(e.signedBy,                                                              ",", true);                int actr = 0;                int cctr = 0;                while (aliases.hasMoreTokens()) {                    String alias = aliases.nextToken().trim();                    if (alias.equals(","))                        cctr++;                    else if (alias.length() > 0)                        actr++;                }                if (actr <= cctr)                    throw new ParsingException(                            st.lineno(),                            ResourcesMgr.getString(                                "SignedBy.has.empty.alias"));                 peekAndMatch(",");            } else if (peekAndMatch("Principal")) {                if (principals == null) {                    principals = new LinkedList<PrincipalEntry>();                }                 String principalClass;                String principalName;                 if (peek("\"")) {                    // both the principalClass and principalName                    // will be replaced later                    principalClass = REPLACE_NAME;                    principalName = match("principal type");                } else {                    // check for principalClass wildcard                    if (peek("*")) {                        match("*");                        principalClass = PrincipalEntry.WILDCARD_CLASS;                    } else {                        principalClass = match("principal type");                    }                     // check for principalName wildcard                    if (peek("*")) {                        match("*");                        principalName = PrincipalEntry.WILDCARD_NAME;                    } else {                        principalName = match("quoted string");                    }                     // disallow WILDCARD_CLASS && actual name                    if (principalClass.equals(PrincipalEntry.WILDCARD_CLASS) &&                        !principalName.equals(PrincipalEntry.WILDCARD_NAME)) {                        if (debug != null) {                                debug.println("disallowing principal that " +                                    "has WILDCARD class but no WILDCARD name");                        }                        throw new ParsingException                                (st.lineno(),                                 ResourcesMgr.getString                                    ("can.not.specify.Principal.with.a.wildcard.class.without.a.wildcard.name"));                    }                }                 try {                    principalName = expand(principalName);                     if (principalClass.equals

Lines 1–500 of 1237.