FileDocCategorySizeDatePackage
PolicyParser.javaAPI DocGlassfish v2 API32917Thu Aug 09 23:10:16 BST 2007com.sun.enterprise.security.provider

PolicyParser

public class PolicyParser extends Object
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.

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.

The Policy init 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.

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:

policy = Policy.getPolicy();
Permissions perms = policy.getPermissions(protectiondomain)

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.

version
1.28, 01/14/00
author
Roland Schemers
author
Ram Marti
since
1.2

Fields Summary
public static final String
REPLACE_NAME
private static final String
EXTDIRS_PROPERTY
private static final String
OLD_EXTDIRS_EXPANSION
static final String
EXTDIRS_EXPANSION
private Vector
grantEntries
private static final Debug
debug
private StreamTokenizer
st
private int
lookahead
private boolean
expandProp
private String
keyStoreUrlString
private String
keyStoreType
private String
keyStoreProvider
private String
storePassURL
Constructors Summary
public PolicyParser()
Creates a PolicyParser object.

	grantEntries = new Vector();
    
public PolicyParser(boolean expandProp)

	this();
	this.expandProp = expandProp;
    
Methods Summary
public voidadd(com.sun.enterprise.security.provider.PolicyParser$GrantEntry ge)

	grantEntries.addElement(ge);
    
private java.lang.Stringexpand(java.lang.String value)


       
	 
    
	return expand(value, false);
    
private java.lang.Stringexpand(java.lang.String value, boolean encodeURL)

	if (!expandProp) {
	    return value;
	} else {
	    return PropertyExpander.expand(value, encodeURL);
	}
    
public java.lang.StringgetKeyStoreProvider()

	return keyStoreProvider;
    
public java.lang.StringgetKeyStoreType()

	return keyStoreType;
    
public java.lang.StringgetKeyStoreUrl()
Returns the (possibly expanded) keystore location, or null if the expansion fails.

	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 java.lang.StringgetStorePassURL()

	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 java.util.EnumerationgrantElements()
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.

	return grantEntries.elements();
    
public static voidmain(java.lang.String[] arg)

	PolicyParser pp = new PolicyParser(true);
	pp.read(new FileReader(arg[0]));
	FileWriter fr = new FileWriter(arg[1]);
	pp.write(fr);
        fr.close();
    
private java.lang.Stringmatch(java.lang.String expect)

	String value = null;
	
	switch (lookahead) {
	case StreamTokenizer.TT_NUMBER:
	    throw new ParsingException(st.lineno(), expect,
				       ResourcesMgr.getString("number ") +
				       String.valueOf(st.nval));
	case StreamTokenizer.TT_EOF:
	    MessageFormat form = new MessageFormat(
	            ResourcesMgr.getString
		            ("expected [expect], read [end of file]"));
	    Object[] source = {expect};
	    throw new ParsingException(form.format(source));
	case StreamTokenizer.TT_WORD:
	    if (expect.equalsIgnoreCase(st.sval)) {
		lookahead = st.nextToken();
	    } else if (expect.equalsIgnoreCase("permission type")) {
		value = st.sval;
		lookahead = st.nextToken();
	    } else if (expect.equalsIgnoreCase("principal type")) {
		value = st.sval;
		lookahead = st.nextToken();
	    } else {
	         throw new ParsingException(st.lineno(), expect,
					    st.sval);
	    }
	    break;
	case '"":
	    if (expect.equalsIgnoreCase("quoted string")) {
		value = st.sval;
		lookahead = st.nextToken();
	    } else if (expect.equalsIgnoreCase("permission type")) {
		value = st.sval;
		lookahead = st.nextToken();
	    } else if (expect.equalsIgnoreCase("principal type")) {
		value = st.sval;
		lookahead = st.nextToken();
	    } else {
		throw new ParsingException(st.lineno(), expect, st.sval);
	    }
	    break;
	case ',":
	    if (expect.equalsIgnoreCase(","))
		lookahead = st.nextToken();
	    else
		throw new ParsingException(st.lineno(), expect, ",");
	    break;
	case '{":
	    if (expect.equalsIgnoreCase("{"))
		lookahead = st.nextToken();
	    else
		throw new ParsingException(st.lineno(), expect, "{");
	    break;
	case '}":
	    if (expect.equalsIgnoreCase("}"))
		lookahead = st.nextToken();
	    else
		throw new ParsingException(st.lineno(), expect, "}");
	    break;
	case ';":
	    if (expect.equalsIgnoreCase(";"))
		lookahead = st.nextToken();
	    else
		throw new ParsingException(st.lineno(), expect, ";");
	    break;
	case '*":
	    if (expect.equalsIgnoreCase("*"))
		lookahead = st.nextToken();
	    else
		throw new ParsingException(st.lineno(), expect, "*");
	    break;
	default:
	    throw new ParsingException(st.lineno(), expect,
			       new String(new char[] {(char)lookahead}));
	}
	return value;
    
static java.lang.String[]parseExtDirs(java.lang.String codebase, int start)


	String s = System.getProperty(EXTDIRS_PROPERTY);
	String globalPrefix = (start > 0 ? codebase.substring(0, start) : "file:");
	int end = start + EXTDIRS_EXPANSION.length();
	String globalSuffix = (end < codebase.length() ? codebase.substring(end) :
	    (String) null);

	String[] dirs = null;
	String localSuffix;
	if (s != null) {
	    StringTokenizer st =
		new StringTokenizer(s, File.pathSeparator);
	    int count = st.countTokens();
	    dirs = new String[count];
	    for (int i = 0; i < count; i++) {
		File file = new File(st.nextToken());
		dirs[i] = sun.net.www.ParseUtil.encodePath
			(file.getAbsolutePath());

		if (!dirs[i].startsWith("/")) {
		    dirs[i] = "/" + dirs[i];
		}

		localSuffix = (globalSuffix == null ?
		    (dirs[i].endsWith("/") ? "*" : "/*") :
		    globalSuffix);

		dirs[i] = globalPrefix + dirs[i] + localSuffix;
	    }
	}
	return dirs;
    
private com.sun.enterprise.security.provider.PolicyParser$GrantEntryparseGrantEntry()
parse a Grant entry

	GrantEntry e = new GrantEntry();
	LinkedList 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();
		}

		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
				("javax.security.auth.x500.X500Principal") &&
			!principalName.equals(PrincipalEntry.WILDCARD_NAME)) {

			// 4702543:  X500 names with an EmailAddress
			// were encoded incorrectly.  construct a new
			// X500Principal with correct encoding.

			X500Principal p = new X500Principal
				((new X500Principal(principalName)).toString());
			principalName = p.getName();
		    }

		    principals.add
			(new PrincipalEntry(principalClass, principalName));
		} catch (PropertyExpander.ExpandException peee) {
		    // ignore the entire policy entry
		    // but continue parsing all the info
		    // so we can get to the next entry
		    if (debug != null) {
			debug.println("principal name expansion failed: " +
					principalName);
		    }
		    ignoreEntry = true;
		}
		peekAndMatch(",");

	    } else {
		throw new ParsingException(st.lineno(),
		                  ResourcesMgr.getString(
				      "expected codeBase or SignedBy or " +
				      "Principal"));
	    }
	}

	if (principals != null) e.principals = principals;
	match("{");

	while(!peek("}")) {
 	    if (peek("Permission")) {
		try {
		    PermissionEntry pe = parsePermissionEntry();
		    e.add(pe);
		} catch (PropertyExpander.ExpandException peee) {
		    // ignore. The add never happened
		    if (debug != null) {
			debug.println(peee.toString());
		    }
		    skipEntry();  // BugId 4219343
		}
		match(";");
  	    } else {
		throw new
		    ParsingException(st.lineno(),
		                     ResourcesMgr.getString(
		                        "expected permission entry"));
	    }
	}
	match("}");

	try {
	    if (e.signedBy != null) e.signedBy = expand(e.signedBy);
	    if (e.codeBase != null) {

		// For backward compatibility with 1.4
		if (e.codeBase.equals(OLD_EXTDIRS_EXPANSION)) {
		    e.codeBase = EXTDIRS_EXPANSION;
		}
		int es;
		if ((es=e.codeBase.indexOf(EXTDIRS_EXPANSION)) < 0) {
		    e.codeBase = expand(e.codeBase, true).replace
					(File.separatorChar, '/");
		} else {
		    // expand the system property "java.ext.dirs",
		    // parse it into its path components,
		    // and then create a grant entry for each component
		    String[] extDirs = parseExtDirs(e.codeBase, es);
		    if (extDirs != null && extDirs.length > 0) {
			for (int i = 0; i < extDirs.length; i++) {
			    GrantEntry newGe = (GrantEntry)e.clone();
			    newGe.codeBase = extDirs[i];
			    add(newGe);

			    if (debug != null) {
				debug.println("creating policy entry for " +
					"expanded java.ext.dirs path:\n\t\t" +
					extDirs[i]);
			    }
			}
		    }
		    ignoreEntry = true;
		}
	    }
	} catch (PropertyExpander.ExpandException peee) {
	    if (debug != null) {
		debug.println(peee.toString());
	    }
	    return null;
	}

	return (ignoreEntry == true) ? null : e;
    
private voidparseKeyStoreEntry()
parses a keystore entry

	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 com.sun.enterprise.security.provider.PolicyParser$PermissionEntryparsePermissionEntry()
parse a Permission entry

	PermissionEntry e = new PermissionEntry();

	// Permission
	match("Permission");
	e.permission = match("permission type");

	if (peek("\"")) {
	    // Permission name
	    e.name = expand(match("quoted string"));
	}

	if (!peek(",")) {
	    return e;
	}
	match(",");

	if (peek("\"")) {
		e.action = expand(match("quoted string"));
		if (!peek(",")) {
		    return e;
		}
		match(",");
	}

	if (peekAndMatch("SignedBy")) {
	    e.signedBy = expand(match("quoted string"));
	}
	return e;
    
private voidparseStorePassURL()

	match("keyStorePasswordURL");
	storePassURL = match("quoted string");
    
private booleanpeek(java.lang.String expect)

	boolean found = false;

	switch (lookahead) {

	case StreamTokenizer.TT_WORD:
	    if (expect.equalsIgnoreCase(st.sval))
		found = true;
	    break;
	case ',":
	    if (expect.equalsIgnoreCase(","))
		found = true;
	    break;
	case '{":
	    if (expect.equalsIgnoreCase("{"))
		found = true;
	    break;
	case '}":
	    if (expect.equalsIgnoreCase("}"))
		found = true;
	    break;
	case '"":
	    if (expect.equalsIgnoreCase("\""))
		found = true;
	    break;
	case '*":
	    if (expect.equalsIgnoreCase("*"))
		found = true;
	    break;
	default:

	}
	return found;
    
private booleanpeekAndMatch(java.lang.String expect)

	if (peek(expect)) {
	    match(expect);
	    return true;
	} else {
	    return false;
	}
    
public voidread(java.io.Reader policy)
Reads a policy configuration into the Policy object using a Reader object.

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.

	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 booleanremove(com.sun.enterprise.security.provider.PolicyParser$GrantEntry ge)

	return grantEntries.removeElement(ge);
    
public voidreplace(com.sun.enterprise.security.provider.PolicyParser$GrantEntry origGe, com.sun.enterprise.security.provider.PolicyParser$GrantEntry newGe)

	grantEntries.setElementAt(newGe, grantEntries.indexOf(origGe));
    
public voidsetKeyStoreProvider(java.lang.String provider)

	keyStoreProvider = provider;
    
public voidsetKeyStoreType(java.lang.String type)

	keyStoreType = type;
    
public voidsetKeyStoreUrl(java.lang.String url)

	keyStoreUrlString = url;
    
public voidsetStorePassURL(java.lang.String storePassURL)

	this.storePassURL = storePassURL;
    
private voidskipEntry()
skip all tokens for this entry leaving the delimiter ";" in the stream.

	while(lookahead != ';") {
	    switch (lookahead) {
	    case StreamTokenizer.TT_NUMBER:
		throw new ParsingException(st.lineno(), ";",
					  ResourcesMgr.getString("number ") +
					  String.valueOf(st.nval));
	    case StreamTokenizer.TT_EOF:
		throw new ParsingException(ResourcesMgr.getString
			("expected [;], read [end of file]"));
	    default:
		lookahead = st.nextToken();
	    }
	}
    
public voidwrite(java.io.Writer policy)
write out the policy

	PrintWriter out = new PrintWriter(new BufferedWriter(policy));

	Enumeration 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 = (GrantEntry) enum_.nextElement();
	    ge.write(out);
	    out.println();
	}
	out.flush();
    
private voidwriteKeyStoreEntry(java.io.PrintWriter out)
writes the (unexpanded) keystore entry

	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 voidwriteStorePassURL(java.io.PrintWriter out)

	out.print("keystorePasswordURL \"");
	out.print(storePassURL);
	out.print('"");
	out.println(";");
	out.println();