1 /* 2 * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 package jaxp.library; 24 25 26 import java.lang.reflect.ReflectPermission; 27 import java.security.CodeSource; 28 import java.security.Permission; 29 import java.security.PermissionCollection; 30 import java.security.Permissions; 31 import java.security.Policy; 32 import java.security.ProtectionDomain; 33 import java.security.SecurityPermission; 34 import java.util.ArrayList; 35 import java.util.Enumeration; 36 import java.util.List; 37 import java.util.PropertyPermission; 38 import java.util.StringJoiner; 39 40 41 /* 42 * This is a base class that every test class must extend if it needs to be run 43 * with security mode. 44 */ 45 public class JAXPPolicyManager { 46 /* 47 * Backing up policy. 48 */ 49 private Policy policyBackup; 50 51 /* 52 * Backing up security manager. 53 */ 54 private SecurityManager smBackup; 55 56 /* 57 * Current policy. 58 */ 59 private TestPolicy policy = new TestPolicy(); 60 61 /* 62 * JAXPPolicyManager singleton. 63 */ 64 private static JAXPPolicyManager policyManager = null; 65 66 /* 67 * Install a SecurityManager along with a default Policy to allow testNG to 68 * run when there is a security manager. 69 */ 70 private JAXPPolicyManager() { 71 // Backing up policy and security manager for restore 72 policyBackup = Policy.getPolicy(); 73 smBackup = System.getSecurityManager(); 74 75 // Set customized policy 76 setDefaultPermissions(); 77 Policy.setPolicy(policy); 78 System.setSecurityManager(new SecurityManager()); 79 } 80 81 static synchronized JAXPPolicyManager getJAXPPolicyManager(boolean createIfNone) { 82 if (policyManager == null & createIfNone) 83 policyManager = new JAXPPolicyManager(); 84 return policyManager; 85 } 86 87 private void teardown() throws Exception { 88 System.setSecurityManager(smBackup); 89 Policy.setPolicy(policyBackup); 90 } 91 92 /* 93 * Restore the original Policy and SecurityManager. 94 */ 95 static synchronized void teardownPolicyManager() throws Exception { 96 if (policyManager != null) { 97 policyManager.teardown(); 98 policyManager = null; 99 } 100 } 101 102 /* 103 * Set default permissions, sub-class of JAXPBaseTest should override this 104 * method. 105 */ 106 private void setDefaultPermissions() { 107 addPermission(new SecurityPermission("getPolicy")); 108 addPermission(new SecurityPermission("setPolicy")); 109 addPermission(new RuntimePermission("getClassLoader")); 110 addPermission(new RuntimePermission("createClassLoader")); 111 addPermission(new RuntimePermission("setSecurityManager")); 112 addPermission(new RuntimePermission("createSecurityManager")); 113 addPermission(new RuntimePermission("modifyThread")); 114 addPermission(new PropertyPermission("*", "read, write")); 115 addPermission(new ReflectPermission("suppressAccessChecks")); 116 addPermission(new RuntimePermission("setIO")); 117 addPermission(new RuntimePermission("setContextClassLoader")); 118 addPermission(new RuntimePermission("accessDeclaredMembers")); 119 } 120 121 /* 122 * Add permission to the TestPolicy. 123 * 124 * @param permission to be added. 125 */ 126 void addPermission(Permission p) { 127 policy.addPermission(p); 128 } 129 130 /* 131 * Add a temporary permission in current thread context. This won't impact 132 * global policy and doesn't support permission combination. 133 * 134 * @param permission 135 * to add. 136 * @return index of the added permission. 137 */ 138 int addTmpPermission(Permission p) { 139 return policy.addTmpPermission(p); 140 } 141 142 /* 143 * Remove a temporary permission from current thread context. 144 * 145 * @param index to remove. 146 * 147 * @throws RuntimeException if no temporary permission list in current 148 * thread context or no permission correlated to the index. 149 */ 150 void removeTmpPermission(int index) { 151 policy.removeTmpPermission(index); 152 } 153 154 155 } 156 157 /* 158 * Simple Policy class that supports the required Permissions to validate the 159 * JAXP concrete classes. 160 */ 161 class TestPolicy extends Policy { 162 private final PermissionCollection permissions = new Permissions(); 163 164 private ThreadLocal<List<Permission>> transientPermissions = new ThreadLocal<>(); 165 166 private static Policy defaultPolicy = Policy.getPolicy(); 167 168 /* 169 * Add permission to this policy. 170 * 171 * @param permission to be added. 172 */ 173 void addPermission(Permission p) { 174 permissions.add(p); 175 } 176 177 /* 178 * Set all permissions. Caution: this should not called carefully unless 179 * it's really needed. 180 * 181 * private void setAllPermissions() { permissions.add(new AllPermission()); 182 * } 183 */ 184 185 /* 186 * Overloaded methods from the Policy class. 187 */ 188 @Override 189 public String toString() { 190 StringJoiner sj = new StringJoiner("\n", "policy: ", ""); 191 Enumeration<Permission> perms = permissions.elements(); 192 while (perms.hasMoreElements()) { 193 sj.add(perms.nextElement().toString()); 194 } 195 return sj.toString(); 196 197 } 198 199 @Override 200 public PermissionCollection getPermissions(ProtectionDomain domain) { 201 return permissions; 202 } 203 204 @Override 205 public PermissionCollection getPermissions(CodeSource codesource) { 206 return permissions; 207 } 208 209 @Override 210 public boolean implies(ProtectionDomain domain, Permission perm) { 211 if (defaultPolicy.implies(domain, perm)) 212 return true; 213 214 if (permissions.implies(perm)) 215 return true; 216 else 217 return tmpImplies(perm); 218 } 219 220 /* 221 * Add a temporary permission in current thread context. This won't impact 222 * global policy and doesn't support permission combination. 223 * 224 * @param permission to add. 225 * @return index of the added permission. 226 */ 227 int addTmpPermission(Permission p) { 228 List<Permission> tmpPermissions = transientPermissions.get(); 229 if (tmpPermissions == null) 230 tmpPermissions = new ArrayList<>(); 231 232 tmpPermissions.add(p); 233 transientPermissions.set(tmpPermissions); 234 return tmpPermissions.size() - 1; 235 } 236 237 /* 238 * Remove a temporary permission from current thread context. 239 * 240 * @param index to remove. 241 * 242 * @throws RuntimeException if no temporary permission list in current 243 * thread context or no permission correlated to the index. 244 */ 245 void removeTmpPermission(int index) { 246 try { 247 List<Permission> tmpPermissions = transientPermissions.get(); 248 tmpPermissions.remove(index); 249 } catch (NullPointerException | IndexOutOfBoundsException e) { 250 throw new RuntimeException("Tried to delete a non-existent temporary permission", e); 251 } 252 } 253 254 /* 255 * Checks to see if the specified permission is implied by temporary 256 * permission list in current thread context. 257 * 258 * @param permission the Permission object to compare. 259 * 260 * @return true if "permission" is implied by any permission in the 261 * temporary permission list, false if not. 262 */ 263 private boolean tmpImplies(Permission perm) { 264 List<Permission> tmpPermissions = transientPermissions.get(); 265 if (tmpPermissions != null) { 266 for (Permission p : tmpPermissions) { 267 if (p.implies(perm)) 268 return true; 269 } 270 } 271 return false; 272 } 273 }