Return-Path: Delivered-To: apmail-incubator-harmony-commits-archive@www.apache.org Received: (qmail 97857 invoked from network); 20 Jan 2006 12:12:17 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (209.237.227.199) by minotaur.apache.org with SMTP; 20 Jan 2006 12:12:17 -0000 Received: (qmail 75966 invoked by uid 500); 20 Jan 2006 12:12:06 -0000 Delivered-To: apmail-incubator-harmony-commits-archive@incubator.apache.org Received: (qmail 75718 invoked by uid 500); 20 Jan 2006 12:12:04 -0000 Mailing-List: contact harmony-commits-help@incubator.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: harmony-dev@incubator.apache.org Delivered-To: mailing list harmony-commits@incubator.apache.org Received: (qmail 75624 invoked by uid 99); 20 Jan 2006 12:12:03 -0000 Received: from asf.osuosl.org (HELO asf.osuosl.org) (140.211.166.49) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 20 Jan 2006 04:12:03 -0800 X-ASF-Spam-Status: No, hits=-9.4 required=10.0 tests=ALL_TRUSTED,NO_REAL_NAME X-Spam-Check-By: apache.org Received: from [209.237.227.194] (HELO minotaur.apache.org) (209.237.227.194) by apache.org (qpsmtpd/0.29) with SMTP; Fri, 20 Jan 2006 04:12:02 -0800 Received: (qmail 97536 invoked by uid 65534); 20 Jan 2006 12:11:42 -0000 Message-ID: <20060120121142.97524.qmail@minotaur.apache.org> Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r370797 - /incubator/harmony/enhanced/classlib/trunk/modules/luni/src/main/java/com/ibm/oti/util/DefaultPolicy.java Date: Fri, 20 Jan 2006 12:11:41 -0000 To: harmony-commits@incubator.apache.org From: tellison@apache.org X-Mailer: svnmailer-1.0.5 X-Virus-Checked: Checked by ClamAV on apache.org X-Spam-Rating: minotaur.apache.org 1.6.2 0/1000/N Author: tellison Date: Fri Jan 20 04:11:35 2006 New Revision: 370797 URL: http://svn.apache.org/viewcvs?rev=370797&view=rev Log: Fix for HARMONY-35 (Harmony ignores java.security.policy property) Modified: incubator/harmony/enhanced/classlib/trunk/modules/luni/src/main/java/com/ibm/oti/util/DefaultPolicy.java Modified: incubator/harmony/enhanced/classlib/trunk/modules/luni/src/main/java/com/ibm/oti/util/DefaultPolicy.java URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/classlib/trunk/modules/luni/src/main/java/com/ibm/oti/util/DefaultPolicy.java?rev=370797&r1=370796&r2=370797&view=diff ============================================================================== --- incubator/harmony/enhanced/classlib/trunk/modules/luni/src/main/java/com/ibm/oti/util/DefaultPolicy.java (original) +++ incubator/harmony/enhanced/classlib/trunk/modules/luni/src/main/java/com/ibm/oti/util/DefaultPolicy.java Fri Jan 20 04:11:35 2006 @@ -1,4 +1,4 @@ -/* Copyright 1998, 2005 The Apache Software Foundation or its licensors, as applicable +/* Copyright 1998, 2006 The Apache Software Foundation or its licensors, as applicable * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,6 +20,7 @@ import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; +import java.io.UnsupportedEncodingException; import java.lang.reflect.Constructor; import java.net.JarURLConnection; import java.net.MalformedURLException; @@ -34,6 +35,8 @@ import java.security.Policy; import java.security.PrivilegedAction; import java.security.Security; +import java.security.UnresolvedPermission; +import java.security.cert.Certificate; import java.util.Enumeration; import java.util.PropertyPermission; import java.util.Vector; @@ -408,7 +411,69 @@ * InputStream Stream containing the policy data */ private void readPolicy(InputStream data, URL source, boolean allowExpand) { - policyRead = false; + // get out if there is no InputStream + if (data == null) + return; + + InputStreamReader dataReader = null; + try { + dataReader = new InputStreamReader(data, "UTF8"); + } catch (UnsupportedEncodingException e1) { + // get out if encoding not available + return; + } + PolicyTokenizer parser = new PolicyTokenizer(dataReader); + + String[] keystoreData = null; + // look for the keystore entry first so that parseGrant + // knows where to get certificates from + Vector thisPolicyGrantList = new Vector(); + Vector unresolvedGrants = new Vector(); + for (int tokenType = parser.nextToken(); !parser.isAtEOF(); tokenType = parser + .nextToken()) { + if (tokenType == PolicyTokenizer.TOK_STRING) { + // all base entries are either grant or keystore entries + if (parser.sval.equalsIgnoreCase("grant")) { + parseGrant(parser, source, thisPolicyGrantList, + unresolvedGrants, allowExpand); + continue; + } + if (parser.sval.equalsIgnoreCase("keystore")) { + if (keystoreData != null) + parser.skipTokens(';'); + else { + keystoreData = new String[2]; + parseKeystore(parser, keystoreData, allowExpand); + } + continue; + } + // if something other than a keystore or grant was reached + // then it was a parse error + grantList.removeAllElements(); + break; + } + // quoted strings at this level are parse errors + grantList.removeAllElements(); + break; + } + + // Add corresponding certificates to each grant + Enumeration e = thisPolicyGrantList.elements(); + while (e.hasMoreElements()) { + GrantHolder grant = (GrantHolder) e.nextElement(); + java.security.cert.Certificate[] certs = null; + String signedBy = grant.getSigner(); + + if (certs != null) { + CodeSource cs = new CodeSource(grant.getCodeSource() + .getLocation(), certs); + grant.setCodeSource(cs); + } + + if (signedBy == null || certs != null) + addGrant(grant); + } + policyRead = true; } /** @@ -682,5 +747,274 @@ } return orgURL; + } + + /** + * read and parse a grant entry + * + */ + private void parseGrant(PolicyTokenizer parser, URL source, + Vector thisPolicyGrantList, Vector unresolvedGrants, + boolean allowExpand) { + // constants for the parsing FSM + final int EXPECT_PERMISSION = 1; + final int EXPECT_PERMISSION_KEYWORD = 2; + final int EXPECT_SIGNEDBY_KEYWORD = 3; + final int EXPECT_NAME = 4; + final int EXPECT_ACTION = 5; + final int EXPECT_SIGNEDBY = 6; + // flag to throw away the entire grant entry + boolean invalidGrant = false; + + String codeBase = null; + String signedBy = null; + while (!parser.isAtEOF()) { + if (parser.nextToken() == PolicyTokenizer.TOK_CHAR) { + if (parser.cval == '{') + break; + // codebase and signer entries can be coma-separated + if (parser.cval == ',' + && (codeBase != null || signedBy != null)) + continue; + // invalid grant + parser.sval = String.valueOf(parser.cval); + } + // a codeBase can be followed by a string giving a location + if (parser.sval.equalsIgnoreCase("codeBase")) { + if (parser.nextToken() != PolicyTokenizer.TOK_QUOTEDSTRING) { + /* + * [MSG "K00a2", "Parsing policy file: {0}, expected quoted + * {1}, found unquoted: {2}"] + */ + System.out.println(com.ibm.oti.util.Msg.getString("K00a2", + new Object[] { source, "codeBase", parser.sval })); + invalidGrant = true; + break; + } + // expand any tags in the codebase + if ((codeBase = expandTags(parser.sval, false, allowExpand)) == null) { + invalidGrant = true; + break; + } + // a codeBase is always specified as a URL, so if this is a + // windows system, convert all the \\ to / + codeBase = codeBase.replace('\\', '/'); + } else if (parser.sval.equalsIgnoreCase("signedBy")) { + if (parser.nextToken() != PolicyTokenizer.TOK_QUOTEDSTRING) { + /* + * [MSG "K00a2", "Parsing policy file: {0}, expected quoted + * {1}, found unquoted: {2}"] + */ + System.out.println(com.ibm.oti.util.Msg.getString("K00a2", + new Object[] { source, "signedBy", parser.sval })); + invalidGrant = true; + continue; + } + signedBy = parser.sval; + } else { + /* + * [MSG "K00a3", "Parsing policy file: {0}, found unexpected: + * {1}"] + */ + System.out.println(com.ibm.oti.util.Msg.getString("K00a3", + source, parser.sval)); + invalidGrant = true; + break; + } + } + + // re-use a GrantHolder from the Hashtable if there already is one + // matching + // the codesource and signers of this entry + GrantHolder thisGrant = null; + try { + CodeSource grantCS = null; + // Generate a codesource name, must be the same + // as the name generated by the class loader + URL hisURL = null; + if (codeBase != null) { + hisURL = toCanonicalURL(new URL(codeBase)); + } + grantCS = new CodeSource(hisURL, (Certificate[])null); + // if a new GrantHolder is needed, create one + if (thisGrant == null) + thisGrant = new GrantHolder(); + thisGrant.setCodeSource(grantCS); + } catch (MalformedURLException e) { + // throw out the entire grant if its URL can't be parsed + invalidGrant = true; + /* + * [MSG "K00a8", "Parsing policy file: {0}, invalid codesource URL: + * {1}"] + */ + System.out.println(com.ibm.oti.util.Msg.getString("K00a8", source, + codeBase)); + } + if (invalidGrant) { + // if there was a parsing failure, throw away the entire + // grant entry and move on + parser.skipTokens('}'); + parser.skipTokens(';'); + return; + } + + thisGrant.setSigner(signedBy); + // parse permission entries + int expect = EXPECT_PERMISSION_KEYWORD; + String permissionClass = null; + String permissionName = null; + String permissionAction = null; + String permissionSigners = null; + while (!parser.isAtEOF()) { + int type = parser.nextToken(); + if (type == PolicyTokenizer.TOK_CHAR) { + if (parser.cval == '}') { + if (parser.nextToken() == PolicyTokenizer.TOK_CHAR) { + if (parser.cval == ';') + break; + parser.sval = String.valueOf(parser.cval); + } + type = -1; // cause an error + // semicolon ends the current permission entry + } else if (parser.cval == ';') { + // perform any tag expansions on the permissionName and + // Action + if (permissionName != null) { + permissionName = expandTags(permissionName, false, + allowExpand); + if (permissionName == null) + continue; + } + if (permissionAction != null) { + permissionAction = expandTags(permissionAction, false, + allowExpand); + if (permissionAction == null) + continue; + } + // create the approprate Permission object for this entry + Permission newPermission = createPermission( + permissionClass, permissionName, permissionAction); + if (newPermission != null) { + thisGrant.addPermission(newPermission); + } else { + if (permissionSigners == null) { + thisGrant.addPermission(new UnresolvedPermission( + permissionClass, permissionName, + permissionAction, null)); + } + } + permissionClass = null; + permissionName = null; + permissionAction = null; + expect = EXPECT_PERMISSION_KEYWORD; + continue; + } else if (parser.cval == ',') { + continue; + } else { + // invalid + parser.sval = String.valueOf(parser.cval); + } + } + + if (type == PolicyTokenizer.TOK_QUOTEDSTRING) { + switch (expect) { + case EXPECT_NAME: + permissionName = parser.sval; + expect = EXPECT_ACTION; + continue; + case EXPECT_ACTION: + permissionAction = parser.sval; + expect = EXPECT_SIGNEDBY_KEYWORD; + continue; + case EXPECT_SIGNEDBY: + permissionSigners = parser.sval; + expect = 0; + continue; + } + // permission must be followed by the object name + } else if (type == PolicyTokenizer.TOK_STRING) { + switch (expect) { + case EXPECT_PERMISSION: + permissionClass = parser.sval; + expect = EXPECT_NAME; + continue; + case EXPECT_PERMISSION_KEYWORD: + if (parser.sval.equalsIgnoreCase("permission")) { + expect = EXPECT_PERMISSION; + continue; + } + break; + case EXPECT_SIGNEDBY_KEYWORD: + case EXPECT_NAME: + case EXPECT_ACTION: + if (parser.sval.equalsIgnoreCase("signedBy")) { + expect = EXPECT_SIGNEDBY; + continue; + } + break; + } + } + /* [MSG "K00a3", "Parsing policy file: {0}, found unexpected: {1}"] */ + System.out.println(com.ibm.oti.util.Msg.getString("K00a3", + new Object[] { source, parser.sval })); + invalidGrant = true; + break; + } + if ((!invalidGrant) || (thisGrant.getPermissions() == null)) + thisPolicyGrantList.addElement(thisGrant); + } + + /** + * and stores the keystore entry if there isn't one already stored + * + * @param parser + * PolicyTokenizer + */ + private void parseKeystore(PolicyTokenizer parser, String[] values, + boolean allowExpand) { + // parse the keystore entry and store it + final int EXPECT_URL = 1; + final int EXPECT_TYPE = 2; + final int EXPECT_END = 3; + int expect = EXPECT_URL; + while (!parser.isAtEOF()) { + switch (parser.nextToken()) { + case PolicyTokenizer.TOK_CHAR: + if (parser.cval == ';') + return; + break; + case PolicyTokenizer.TOK_QUOTEDSTRING: + if (expect == EXPECT_URL) { + expect = EXPECT_TYPE; + String keyURL = expandTags(parser.sval, true, allowExpand); + values[0] = keyURL.replace('\\', '/'); + break; + } + if (expect == EXPECT_TYPE) { + expect = EXPECT_END; + values[1] = parser.sval; + break; + } + break; + } + } + } + + /** + * @param grant + */ + private void addGrant(GrantHolder grant) { + // Signer no longer required, the certificates have been added + grant.setSigner(null); + for (int i = 0; i < grantList.size(); i++) { + GrantHolder existingGrant = (GrantHolder) grantList.elementAt(i); + if (existingGrant.getCodeSource().equals(grant.getCodeSource())) { + Enumeration egl = grant.getPermissions().elements(); + while (egl.hasMoreElements()) + existingGrant.addPermission((Permission) egl.nextElement()); + return; + } + } + grantList.addElement(grant); } }