--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/security/Policy/ExtensiblePolicy/ExtensiblePolicyTest.java Sat Sep 26 12:08:55 2015 +0300
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2015, 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.
+ *
+ * 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.
+ */
+
+import TVJar.TVPermission;
+import java.security.AccessController;
+
+/**
+ * @test @bug 8050402
+ * @summary Check policy is extensible with user defined permissions
+ * @run main/othervm/policy=ExtensiblePolicyTest1.policy
+ * ExtensiblePolicyTest false
+ * @run main/othervm/policy=ExtensiblePolicyTest2.policy
+ * ExtensiblePolicyTest true
+ * @run main/othervm/policy=ExtensiblePolicyTest3.policy
+ * ExtensiblePolicyTest true
+ */
+public class ExtensiblePolicyTest {
+
+ public static void main(String args[]) throws Throwable {
+ // ExtensiblePolicyTest1.policy: policy file grants permission to
+ // watch TVChannel 3-6
+ // ExtensiblePolicyTest2.policy: policy file grants permission to
+ // watch TVChanel 4
+ // ExtensiblePolicyTest3.policy: policy file grants permission signed
+ // by duke2 to watch TVChanel 5
+
+ TVPermission perm = new TVPermission("channel:5", "watch");
+ boolean getException = false;
+ String exceptionMessage = null;
+ boolean expectException = Boolean.parseBoolean(args[0]);
+ try {
+ AccessController.checkPermission(perm);
+ } catch (SecurityException se) {
+ getException = true;
+ exceptionMessage = se.getMessage();
+ }
+
+ if (expectException ^ getException) {
+ throw new RuntimeException("Test Failed: expectException = "
+ + expectException + " getException = " + getException
+ + "\n" + exceptionMessage);
+ }
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/security/Policy/ExtensiblePolicy/ExtensiblePolicyTest1.policy Sat Sep 26 12:08:55 2015 +0300
@@ -0,0 +1,4 @@
+grant {
+ permission TVJar.TVPermission "channel:3-6", "watch";
+};
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/security/Policy/ExtensiblePolicy/ExtensiblePolicyTest2.policy Sat Sep 26 12:08:55 2015 +0300
@@ -0,0 +1,3 @@
+grant {
+ permission TVJar.TVPermission "channel:4", "watch";
+};
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/security/Policy/ExtensiblePolicy/ExtensiblePolicyTest3.policy Sat Sep 26 12:08:55 2015 +0300
@@ -0,0 +1,5 @@
+keystore "file:${user.dir}/epkeystore";
+
+grant {
+ permission TVJar.TVPermission "channel:5", "watch", SignedBy "duke2";
+};
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/security/Policy/ExtensiblePolicy/ExtensiblePolicyWithJarTest.java Sat Sep 26 12:08:55 2015 +0300
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 2015, 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.
+ *
+ * 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.
+ */
+
+import TVJar.TVPermission;
+import java.io.File;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.security.AccessController;
+import jdk.testlibrary.ProcessTools;
+import jdk.testlibrary.JarUtils;
+
+/**
+ * @test
+ * @bug 8050402
+ * @summary Check policy is extensible with user defined permissions
+ * @library /lib/testlibrary
+ * @compile TVJar/TVPermission.java
+ * @run main ExtensiblePolicyWithJarTest
+ */
+public class ExtensiblePolicyWithJarTest {
+
+ public static void main(String args[]) throws Throwable {
+ final String FS = File.separator;
+ final String PS = File.pathSeparator;
+ final String POL = "ExtensiblePolicyTest3.policy";
+ final String JAVA_HOME = System.getProperty("test.jdk");
+ final String KEYTOOL = JAVA_HOME + FS + "bin" + FS + "keytool";
+ final String JARSIGNER = JAVA_HOME + FS + "bin" + FS + "jarsigner";
+ final String KEYSTORE = "epkeystore";
+ final String PASSWORD = "password";
+ final String ALIAS = "duke2";
+ final String CLASSPATH = System.getProperty("test.class.path", "");
+ final String TESTCLASSES = System.getProperty("test.classes", "");
+ final String TVPERMJAR = "tvPerm.jar";
+ final String PATHTOJAR = System.getProperty("user.dir", "")
+ + FS + TVPERMJAR;
+
+ // create jar file for TVpermission
+ new File("TVJar").mkdir();
+ Files.copy(Paths.get(TESTCLASSES + FS + "TVJar", "TVPermission.class"),
+ Paths.get("TVJar", "TVPermission.class"));
+ Files.copy(Paths.get(TESTCLASSES + FS + "TVJar",
+ "TVPermissionCollection.class"),
+ Paths.get("TVJar", "TVPermissionCollection.class"));
+ JarUtils.createJar(TVPERMJAR, "TVJar/TVPermission.class",
+ "TVJar/TVPermissionCollection.class");
+
+ // create key pair for jar signing
+ ProcessTools.executeCommand(KEYTOOL,
+ "-genkey",
+ "-alias", ALIAS,
+ "-keystore", KEYSTORE,
+ "-storetype", "JKS",
+ "-keypass", PASSWORD,
+ "-dname", "cn=Blah",
+ "-storepass", PASSWORD
+ ).shouldHaveExitValue(0);
+ // sign jar
+ ProcessTools.executeCommand(JARSIGNER,
+ "-keystore", KEYSTORE,
+ "-storepass", PASSWORD,
+ "-keypass", PASSWORD,
+ TVPERMJAR,
+ ALIAS).shouldHaveExitValue(0);
+ // add jar file to classpath
+ String cp = PATHTOJAR + PS + CLASSPATH;
+
+ // policy file grants permission signed by duke2 to watch TVChanel 5
+ try {
+ String[] cmd = {
+ "-classpath", cp,
+ "-Djava.security.manager",
+ "-Djava.security.policy=" + POL,
+ "ExtensiblePolicyTest_orig$TestMain"};
+ ProcessTools.executeTestJvm(cmd).shouldHaveExitValue(0);
+ } catch (Exception ex) {
+ System.out.println("ExtensiblePolicyWithJarTest Failed");
+ }
+
+ }
+
+ public static class TestMain {
+ public static void main(String args[]) {
+ TVPermission perm = new TVPermission("channel:5", "watch");
+ try {
+ AccessController.checkPermission(perm);
+ } catch (SecurityException se) {
+ throw new RuntimeException(se);
+ }
+ }
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/security/Policy/ExtensiblePolicy/TVJar/TVPermission.java Sat Sep 26 12:08:55 2015 +0300
@@ -0,0 +1,358 @@
+/*
+ * Copyright (c) 1999, 2015, 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.
+ *
+ * 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 TVJar;
+
+import java.security.Permission;
+import java.security.PermissionCollection;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.Iterator;
+import java.util.StringJoiner;
+import java.util.StringTokenizer;
+
+public class TVPermission extends Permission {
+
+ /**
+ * Watch
+ */
+ private final static int WATCH = 0x1;
+
+ /**
+ * Preview
+ */
+ private final static int PREVIEW = 0x2;
+
+ /**
+ * No actions
+ */
+ private final static int NONE = 0x0;
+
+ /**
+ * All actions
+ */
+ private final static int ALL = WATCH | PREVIEW;
+
+ // the actions mask
+ private int mask;
+
+ // the actions string
+ private String actions;
+
+ // the canonical name of the channel
+ private String cname;
+
+ // true if the channelname is a wildcard
+ private boolean wildcard;
+
+ // num range on channel
+ private int[] numrange;
+
+ // various num constants
+ private final static int NUM_MIN = 1;
+ private final static int NUM_MAX = 128;
+
+ public TVPermission(String channel, String action) {
+ this(channel, getMask(action));
+ }
+
+ TVPermission(String channel, int mask) {
+ super(channel);
+ init(channel, mask);
+ }
+
+ private synchronized int[] parseNum(String num)
+ throws Exception {
+
+ if (num == null || num.equals("") || num.equals("*")) {
+ wildcard = true;
+ return new int[]{NUM_MIN, NUM_MAX};
+ }
+
+ int dash = num.indexOf('-');
+
+ if (dash == -1) {
+ int p = 0;
+ try {
+ p = Integer.parseInt(num);
+ } catch (NumberFormatException nfe) {
+ throw new IllegalArgumentException("invalid input" + num);
+ }
+ return new int[]{p, p};
+ } else {
+ String low = num.substring(0, dash);
+ String high = num.substring(dash + 1);
+ int l, h;
+
+ if (low.equals("")) {
+ l = NUM_MIN;
+ } else {
+ try {
+ l = Integer.parseInt(low);
+ } catch (NumberFormatException nfe) {
+ throw new IllegalArgumentException("invalid input" + num);
+ }
+ }
+
+ if (high.equals("")) {
+ h = NUM_MAX;
+ } else {
+ try {
+ h = Integer.parseInt(high);
+ } catch (NumberFormatException nfe) {
+ throw new IllegalArgumentException("invalid input" + num);
+ }
+ }
+ if (h < l || l < NUM_MIN || h > NUM_MAX) {
+ throw new IllegalArgumentException("invalid num range");
+ }
+
+ return new int[]{l, h};
+ }
+ }
+
+ /**
+ * Initialize the TVPermission object.
+ */
+ private synchronized void init(String channel, int mask) {
+
+ // Parse the channel name.
+ int sep = channel.indexOf(':');
+
+ if (sep != -1) {
+ String num = channel.substring(sep + 1);
+ cname = channel.substring(0, sep);
+ try {
+ numrange = parseNum(num);
+ } catch (Exception e) {
+ throw new IllegalArgumentException("invalid num range: " + num);
+ }
+ } else {
+ numrange = new int[]{NUM_MIN, NUM_MAX};
+ }
+ }
+
+ /**
+ * Convert an action string to an integer actions mask.
+ *
+ * @param action the action string
+ * @return the action mask
+ */
+ private synchronized static int getMask(String action) {
+ int mask = NONE;
+
+ if (action == null) {
+ return mask;
+ }
+
+ StringTokenizer st = new StringTokenizer(action.toLowerCase(), ",");
+ while (st.hasMoreTokens()) {
+ String token = st.nextToken();
+ if (token.equals("watch")) {
+ mask |= WATCH;
+ } else if (token.equals("preview")) {
+ mask |= PREVIEW;
+ } else {
+ throw new IllegalArgumentException("invalid TV permission: " + token);
+ }
+ }
+ return mask;
+ }
+
+ @Override
+ public boolean implies(Permission p) {
+ if (!(p instanceof TVPermission)) {
+ return false;
+ }
+
+ if (this.wildcard) {
+ return true;
+ }
+
+ TVPermission that = (TVPermission) p;
+
+ if ((this.mask & that.mask) != that.mask) {
+ System.out.println("Masks are not ok this = "
+ + this.mask + "THat = " + that.mask);
+ return false;
+ }
+
+ if ((this.numrange[0] > that.numrange[0])
+ || (this.numrange[1] < that.numrange[1])) {
+
+ System.out.println("This 0= " + this.numrange[0]
+ + " 1 = " + this.numrange[1]);
+ System.out.println("That 0= " + that.numrange[0]
+ + " 1 = " + that.numrange[1]);
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Checks two TVPermission objects for equality.
+ * <p>
+ * @param obj the object we are testing for equality.
+ * @return true if obj is a TVPermission, and has the same channelname and
+ * action mask as this TVPermission object.
+ */
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == this) {
+ return true;
+ }
+
+ if (!(obj instanceof TVPermission)) {
+ return false;
+ }
+
+ TVPermission that = (TVPermission) obj;
+
+ // check the mask first
+ if (this.mask != that.mask) {
+ return false;
+ }
+
+ // now check the num range...
+ if ((this.numrange[0] != that.numrange[0])
+ || (this.numrange[1] != that.numrange[1])) {
+ return false;
+ }
+
+ return this.getName().equals(that.getName());
+ }
+
+ /**
+ * Returns the hash code value for this object.
+ *
+ * @return a hash code value for this object.
+ */
+ @Override
+ public int hashCode() {
+ return this.getName().hashCode();
+ }
+
+ /**
+ * Return the canonical string representation of the actions. Always returns
+ * actions in the following order: watch,preview.
+ *
+ * @param mask a specific integer action mask to translate into a string
+ * @return the canonical string representation of the actions
+ */
+ private synchronized static String getActions(int mask) {
+ StringJoiner sj = new StringJoiner(",");
+ if ((mask & WATCH) == WATCH) {
+ sj.add("watch");
+ }
+ if ((mask & PREVIEW) == PREVIEW) {
+ sj.add("preview");
+ }
+ return sj.toString();
+ }
+
+ /**
+ * Return the canonical string representation of the actions. Always returns
+ * actions in the following order: watch,preview.
+ *
+ * @return the canonical string representation of the actions.
+ */
+ @Override
+ public String getActions() {
+ if (actions == null) {
+ actions = getActions(this.mask);
+ }
+
+ return actions;
+ }
+
+ @Override
+ public String toString() {
+ return super.toString() + "\n"
+ + "cname = " + cname + "\n"
+ + "wildcard = " + wildcard + "\n"
+ + "numrange = " + numrange[0] + "," + numrange[1] + "\n";
+
+ }
+
+ @Override
+ public PermissionCollection newPermissionCollection() {
+ return new TVPermissionCollection();
+ }
+}
+
+final class TVPermissionCollection extends PermissionCollection {
+
+ /**
+ * The TVPermissions for this set.
+ */
+ private final ArrayList<TVPermission> permissions = new ArrayList<>();
+
+ /**
+ * Adds a permission to the TVPermissions. The key for the hash is the name
+ * in the case of wildcards, or all the IP addresses.
+ *
+ * @param permission the Permission object to add.
+ */
+ @Override
+ public void add(Permission permission) {
+ if (!(permission instanceof TVPermission)) {
+ throw new IllegalArgumentException("invalid permission: " + permission);
+ }
+ permissions.add((TVPermission) permission);
+ }
+
+ /**
+ * Check and see if this collection of permissions implies the permissions
+ * expressed in "permission".
+ *
+ * @param p the Permission object to compare
+ *
+ * @return true if "permission" is a proper subset of a permission in the
+ * collection, false if not.
+ */
+ @Override
+ public boolean implies(Permission p) {
+ if (!(p instanceof TVPermission)) {
+ return false;
+ }
+
+ Iterator<TVPermission> i = permissions.iterator();
+ while (i.hasNext()) {
+ if (((TVPermission) i.next()).implies(p)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Returns an enumeration of all the TVPermission objects in the container.
+ *
+ * @return an enumeration of all the TVPermission objects.
+ */
+ @Override
+ public Enumeration elements() {
+ return Collections.enumeration(permissions);
+ }
+
+}