DefaultPolicyParserpublic class DefaultPolicyParser extends Object This is a basic loader of policy files. It delegates lexical analysis to
a pluggable scanner and converts received tokens to a set of
{@link org.apache.harmony.security.PolicyEntry PolicyEntries}.
For details of policy format, see the
{@link org.apache.harmony.security.fortress.DefaultPolicy default policy
description}.
For ordinary uses, this class has just one public method parse() ,
which performs the main task.
Extensions of this parser may redefine specific operations separately,
by overriding corresponding protected methods.
This implementation is effectively thread-safe, as it has no field references
to data being processed (that is, passes all the data as method parameters). |
Fields Summary |
---|
private final org.apache.harmony.security.DefaultPolicyScanner | scanner |
Constructors Summary |
---|
public DefaultPolicyParser()Default constructor,
{@link org.apache.harmony.security.DefaultPolicyScanner DefaultPolicyScanner}
is used.
scanner = new DefaultPolicyScanner();
| public DefaultPolicyParser(org.apache.harmony.security.DefaultPolicyScanner s)Extension constructor for plugging-in custom scanner.
this.scanner = s;
|
Methods Summary |
---|
protected java.security.Principal | getPrincipalByAlias(java.security.KeyStore ks, java.lang.String alias)Returns a subject's X500Principal of an X509Certificate,
which is associated with the specified keystore alias.
if (ks == null) {
throw new KeyStoreException(
Messages.getString("security.147", alias)); //$NON-NLS-1$
}
//XXX cache found certs ??
Certificate x509 = ks.getCertificate(alias);
if (x509 instanceof X509Certificate) {
return ((X509Certificate) x509).getSubjectX500Principal();
} else {
throw new CertificateException(Messages.getString("security.148", //$NON-NLS-1$
alias, x509));
}
| protected java.security.KeyStore | initKeyStore(java.util.List keystores, java.net.URL base, java.util.Properties system, boolean resolve)Returns the first successfully loaded KeyStore, from the specified list of
possible locations. This method iterates over the list of KeystoreEntries;
for each entry expands url and type ,
tries to construct instances of specified URL and KeyStore and to load
the keystore. If it is loaded, returns the keystore, otherwise proceeds to
the next KeystoreEntry.
Note: an url may be relative to the policy file location or absolute.
for (int i = 0; i < keystores.size(); i++) {
try {
DefaultPolicyScanner.KeystoreEntry ke = keystores
.get(i);
if (resolve) {
ke.url = PolicyUtils.expandURL(ke.url, system);
if (ke.type != null) {
ke.type = PolicyUtils.expand(ke.type, system);
}
}
if (ke.type == null || ke.type.length() == 0) {
ke.type = KeyStore.getDefaultType();
}
KeyStore ks = KeyStore.getInstance(ke.type);
URL location = new URL(base, ke.url);
InputStream is = AccessController
.doPrivileged(new PolicyUtils.URLLoader(location));
try {
ks.load(is, null);
}
finally {
is.close();
}
return ks;
}
catch (Exception e) {
// TODO: log warning
}
}
return null;
| public java.util.Collection | parse(java.net.URL location, java.util.Properties system)This is the main business method. It manages loading process as follows:
the associated scanner is used to parse the stream to a set of
{@link org.apache.harmony.security.DefaultPolicyScanner.GrantEntry composite tokens},
then this set is iterated and each token is translated to a PolicyEntry.
Semantically invalid tokens are ignored, the same as void PolicyEntries.
A policy file may refer to some KeyStore(s), and in this case the first
valid reference is initialized and used in processing tokens.
boolean resolve = PolicyUtils.canExpandProperties();
// BEGIN android-modified
Reader r =
new BufferedReader(
new InputStreamReader(
AccessController.doPrivileged(
new PolicyUtils.URLLoader(location))),
8192);
// END android-modified
Collection<GrantEntry> grantEntries = new HashSet<GrantEntry>();
List<KeystoreEntry> keystores = new ArrayList<KeystoreEntry>();
try {
scanner.scanStream(r, grantEntries, keystores);
}
finally {
r.close();
}
//XXX KeyStore could be loaded lazily...
KeyStore ks = initKeyStore(keystores, location, system, resolve);
Collection<PolicyEntry> result = new HashSet<PolicyEntry>();
for (Iterator<GrantEntry> iter = grantEntries.iterator(); iter.hasNext();) {
DefaultPolicyScanner.GrantEntry ge = iter
.next();
try {
PolicyEntry pe = resolveGrant(ge, ks, system, resolve);
if (!pe.isVoid()) {
result.add(pe);
}
}
catch (Exception e) {
// TODO: log warning
}
}
return result;
| protected org.apache.harmony.security.PolicyEntry | resolveGrant(org.apache.harmony.security.DefaultPolicyScanner.GrantEntry ge, java.security.KeyStore ks, java.util.Properties system, boolean resolve)Translates GrantEntry token to PolicyEntry object. It goes step by step,
trying to resolve each component of the GrantEntry:
- If
codebase is specified, expand it and construct an URL.
- If
signers is specified, expand it and obtain
corresponding Certificates.
- If
principals collection is specified, iterate over it.
For each PrincipalEntry, expand name and if no class specified,
resolve actual X500Principal from a KeyStore certificate; otherwise keep it
as UnresolvedPrincipal.
- Iterate over
permissions collection. For each PermissionEntry,
try to resolve (see method
{@link #resolvePermission(DefaultPolicyScanner.PermissionEntry, DefaultPolicyScanner.GrantEntry, KeyStore, Properties, boolean) resolvePermission()})
a corresponding permission. If resolution failed, ignore the PermissionEntry.
In fact, property expansion in the steps above is conditional and is ruled by
the parameter resolve.
Finally a new PolicyEntry is created, which associates the trinity
of resolved URL, Certificates and Principals to a set of granted Permissions.
URL codebase = null;
Certificate[] signers = null;
Set<Principal>principals = new HashSet<Principal>();
Set<Permission>permissions = new HashSet<Permission>();
if (ge.codebase != null) {
codebase = new URL(resolve ? PolicyUtils.expandURL(ge.codebase,
system) : ge.codebase);
//Fix HARMONY-1963
if ("file".equals(codebase.getProtocol())) { //$NON-NLS-1$
File codeFile = new File(codebase.getFile());
if (codeFile.isAbsolute()) {
codebase = new URL("file://" + //$NON-NLS-1$
codeFile.getAbsolutePath());
}
}
}
if (ge.signers != null) {
if (resolve) {
ge.signers = PolicyUtils.expand(ge.signers, system);
}
signers = resolveSigners(ks, ge.signers);
}
if (ge.principals != null) {
for (Iterator<PrincipalEntry> iter = ge.principals.iterator(); iter.hasNext();) {
DefaultPolicyScanner.PrincipalEntry pe = iter
.next();
if (resolve) {
pe.name = PolicyUtils.expand(pe.name, system);
}
if (pe.klass == null) {
principals.add(getPrincipalByAlias(ks, pe.name));
} else {
principals.add(new UnresolvedPrincipal(pe.klass, pe.name));
}
}
}
if (ge.permissions != null) {
for (Iterator<PermissionEntry> iter = ge.permissions.iterator(); iter.hasNext();) {
DefaultPolicyScanner.PermissionEntry pe = iter
.next();
try {
permissions.add(resolvePermission(pe, ge, ks, system,
resolve));
}
catch (Exception e) {
// TODO: log warning
}
}
}
return new PolicyEntry(new CodeSource(codebase, signers), principals,
permissions);
| protected java.security.Permission | resolvePermission(org.apache.harmony.security.DefaultPolicyScanner.PermissionEntry pe, org.apache.harmony.security.DefaultPolicyScanner.GrantEntry ge, java.security.KeyStore ks, java.util.Properties system, boolean resolve)Translates PermissionEntry token to Permission object.
First, it performs general expansion for non-null name and
properties expansion for non-null name , action
and signers .
Then, it obtains signing Certificates(if any), tries to find a class specified by
klass name and instantiate a corresponding permission object.
If class is not found or it is signed improperly, returns UnresolvedPermission.
if (pe.name != null) {
pe.name = PolicyUtils.expandGeneral(pe.name,
new PermissionExpander().configure(ge, ks));
}
if (resolve) {
if (pe.name != null) {
pe.name = PolicyUtils.expand(pe.name, system);
}
if (pe.actions != null) {
pe.actions = PolicyUtils.expand(pe.actions, system);
}
if (pe.signers != null) {
pe.signers = PolicyUtils.expand(pe.signers, system);
}
}
Certificate[] signers = (pe.signers == null) ? null : resolveSigners(
ks, pe.signers);
try {
Class<?> klass = Class.forName(pe.klass);
if (PolicyUtils.matchSubset(signers, klass.getSigners())) {
return PolicyUtils.instantiatePermission(klass, pe.name,
pe.actions);
}
}
catch (ClassNotFoundException cnfe) {}
//maybe properly signed class will be loaded later
return new UnresolvedPermission(pe.klass, pe.name, pe.actions, signers);
| protected java.security.cert.Certificate[] | resolveSigners(java.security.KeyStore ks, java.lang.String signers)Takes a comma-separated list of aliases and obtains corresponding
certificates.
if (ks == null) {
throw new KeyStoreException(Messages.getString("security.146", //$NON-NLS-1$
signers));
}
Collection<Certificate> certs = new HashSet<Certificate>();
StringTokenizer snt = new StringTokenizer(signers, ","); //$NON-NLS-1$
while (snt.hasMoreTokens()) {
//XXX cache found certs ??
certs.add(ks.getCertificate(snt.nextToken().trim()));
}
return certs.toArray(new Certificate[certs.size()]);
|
|