1 /* 2 * Copyright (c) 1995, 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. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package sun.applet; 27 28 import java.io.File; 29 import java.io.FilePermission; 30 import java.io.IOException; 31 import java.io.FileDescriptor; 32 import java.net.URL; 33 import java.net.URLClassLoader; 34 import java.net.InetAddress; 35 import java.net.UnknownHostException; 36 import java.net.SocketPermission; 37 import java.util.Enumeration; 38 import java.util.Iterator; 39 import java.util.HashSet; 40 import java.util.StringTokenizer; 41 import java.security.*; 42 import java.lang.reflect.*; 43 import jdk.internal.misc.JavaNetURLClassLoaderAccess; 44 import jdk.internal.misc.JavaSecurityAccess; 45 import jdk.internal.misc.SharedSecrets; 46 import sun.awt.AWTSecurityManager; 47 import sun.awt.AppContext; 48 import sun.awt.AWTPermissions; 49 import sun.security.util.SecurityConstants; 50 51 52 53 /** 54 * This class defines an applet security policy 55 * 56 */ 57 public 58 class AppletSecurity extends AWTSecurityManager { 59 private static final JavaNetURLClassLoaderAccess JNUCLA 60 = SharedSecrets.getJavaNetURLClassLoaderAccess(); 61 private static final JavaSecurityAccess JSA = SharedSecrets.getJavaSecurityAccess(); 62 63 /** 64 * Construct and initialize. 65 */ 66 public AppletSecurity() { 67 reset(); 68 } 69 70 // Cache to store known restricted packages 71 private HashSet<String> restrictedPackages = new HashSet<>(); 72 73 /** 74 * Reset from Properties 75 */ 76 public void reset() 77 { 78 // Clear cache 79 restrictedPackages.clear(); 80 81 AccessController.doPrivileged(new PrivilegedAction<Object>() { 82 public Object run() 83 { 84 // Enumerate system properties 85 Enumeration<?> e = System.getProperties().propertyNames(); 86 87 while (e.hasMoreElements()) 88 { 89 String name = (String) e.nextElement(); 90 91 if (name != null && name.startsWith("package.restrict.access.")) 92 { 93 String value = System.getProperty(name); 94 95 if (value != null && value.equalsIgnoreCase("true")) 96 { 97 String pkg = name.substring(24); 98 99 // Cache restricted packages 100 restrictedPackages.add(pkg); 101 } 102 } 103 } 104 return null; 105 } 106 }); 107 } 108 109 /** 110 * get the current (first) instance of an AppletClassLoader on the stack. 111 */ 112 @SuppressWarnings({"deprecation", 113 "removal"}) // SecurityManager.currentClassLoader() 114 private AppletClassLoader currentAppletClassLoader() 115 { 116 // try currentClassLoader first 117 ClassLoader loader = currentClassLoader(); 118 119 if ((loader == null) || (loader instanceof AppletClassLoader)) 120 return (AppletClassLoader)loader; 121 122 // if that fails, get all the classes on the stack and check them. 123 Class<?>[] context = getClassContext(); 124 for (int i = 0; i < context.length; i++) { 125 loader = context[i].getClassLoader(); 126 if (loader instanceof AppletClassLoader) 127 return (AppletClassLoader)loader; 128 } 129 130 /* 131 * fix bug # 6433620 the logic here is : try to find URLClassLoader from 132 * class context, check its AccessControlContext to see if 133 * AppletClassLoader is in stack when it's created. for this kind of 134 * URLClassLoader, return the AppContext associated with the 135 * AppletClassLoader. 136 */ 137 for (int i = 0; i < context.length; i++) { 138 final ClassLoader currentLoader = context[i].getClassLoader(); 139 140 if (currentLoader instanceof URLClassLoader) { 141 URLClassLoader ld = (URLClassLoader)currentLoader; 142 loader = AccessController.doPrivileged( 143 new PrivilegedAction<ClassLoader>() { 144 public ClassLoader run() { 145 146 AccessControlContext acc = null; 147 ProtectionDomain[] pds = null; 148 149 try { 150 acc = JNUCLA.getAccessControlContext(ld); 151 if (acc == null) { 152 return null; 153 } 154 155 pds = JSA.getProtectDomains(acc); 156 if (pds == null) { 157 return null; 158 } 159 } catch (Exception e) { 160 throw new UnsupportedOperationException(e); 161 } 162 163 for (int i=0; i<pds.length; i++) { 164 ClassLoader cl = pds[i].getClassLoader(); 165 166 if (cl instanceof AppletClassLoader) { 167 return cl; 168 } 169 } 170 171 return null; 172 } 173 }); 174 175 if (loader != null) { 176 return (AppletClassLoader) loader; 177 } 178 } 179 } 180 181 // if that fails, try the context class loader 182 loader = Thread.currentThread().getContextClassLoader(); 183 if (loader instanceof AppletClassLoader) 184 return (AppletClassLoader)loader; 185 186 // no AppletClassLoaders on the stack 187 return (AppletClassLoader)null; 188 } 189 190 /** 191 * Returns true if this threadgroup is in the applet's own thread 192 * group. This will return false if there is no current class 193 * loader. 194 */ 195 protected boolean inThreadGroup(ThreadGroup g) { 196 if (currentAppletClassLoader() == null) 197 return false; 198 else 199 return getThreadGroup().parentOf(g); 200 } 201 202 /** 203 * Returns true of the threadgroup of thread is in the applet's 204 * own threadgroup. 205 */ 206 protected boolean inThreadGroup(Thread thread) { 207 return inThreadGroup(thread.getThreadGroup()); 208 } 209 210 /** 211 * Applets are not allowed to manipulate threads outside 212 * applet thread groups. However a terminated thread no longer belongs 213 * to any group. 214 */ 215 public void checkAccess(Thread t) { 216 /* When multiple applets is reloaded simultaneously, there will be 217 * multiple invocations to this method from plugin's SecurityManager. 218 * This method should not be synchronized to avoid deadlock when 219 * a page with multiple applets is reloaded 220 */ 221 if ((t.getState() != Thread.State.TERMINATED) && !inThreadGroup(t)) { 222 checkPermission(SecurityConstants.MODIFY_THREAD_PERMISSION); 223 } 224 } 225 226 private boolean inThreadGroupCheck = false; 227 228 /** 229 * Applets are not allowed to manipulate thread groups outside 230 * applet thread groups. 231 */ 232 public synchronized void checkAccess(ThreadGroup g) { 233 if (inThreadGroupCheck) { 234 // if we are in a recursive check, it is because 235 // inThreadGroup is calling appletLoader.getThreadGroup 236 // in that case, only do the super check, as appletLoader 237 // has a begin/endPrivileged 238 checkPermission(SecurityConstants.MODIFY_THREADGROUP_PERMISSION); 239 } else { 240 try { 241 inThreadGroupCheck = true; 242 if (!inThreadGroup(g)) { 243 checkPermission(SecurityConstants.MODIFY_THREADGROUP_PERMISSION); 244 } 245 } finally { 246 inThreadGroupCheck = false; 247 } 248 } 249 } 250 251 252 /** 253 * Throws a {@code SecurityException} if the 254 * calling thread is not allowed to access the package specified by 255 * the argument. 256 * <p> 257 * This method is used by the {@code loadClass} method of class 258 * loaders. 259 * <p> 260 * The {@code checkPackageAccess} method for class 261 * {@code SecurityManager} calls 262 * {@code checkPermission} with the 263 * {@code RuntimePermission("accessClassInPackage."+ pkgname)} 264 * permission. 265 * 266 * @param pkgname the package name. 267 * @exception SecurityException if the caller does not have 268 * permission to access the specified package. 269 * @see java.lang.ClassLoader#loadClass(java.lang.String, boolean) 270 */ 271 public void checkPackageAccess(final String pkgname) { 272 273 // first see if the VM-wide policy allows access to this package 274 super.checkPackageAccess(pkgname); 275 276 // now check the list of restricted packages 277 for (Iterator<String> iter = restrictedPackages.iterator(); iter.hasNext();) 278 { 279 String pkg = iter.next(); 280 281 // Prevent matching "sun" and "sunir" even if they 282 // starts with similar beginning characters 283 // 284 if (pkgname.equals(pkg) || pkgname.startsWith(pkg + ".")) 285 { 286 checkPermission(new java.lang.RuntimePermission 287 ("accessClassInPackage." + pkgname)); 288 } 289 } 290 } 291 292 /** 293 * Tests if a client can get access to the AWT event queue. 294 * <p> 295 * This method calls {@code checkPermission} with the 296 * {@code AWTPermission("accessEventQueue")} permission. 297 * 298 * @since 1.1 299 * @exception SecurityException if the caller does not have 300 * permission to access the AWT event queue. 301 */ 302 @SuppressWarnings({"deprecation", 303 "removal"}) // SecurityManager.checkAwtEventQueueAccess 304 public void checkAwtEventQueueAccess() { 305 AppContext appContext = AppContext.getAppContext(); 306 AppletClassLoader appletClassLoader = currentAppletClassLoader(); 307 308 if (AppContext.isMainContext(appContext) && (appletClassLoader != null)) { 309 // If we're about to allow access to the main EventQueue, 310 // and anything untrusted is on the class context stack, 311 // disallow access. 312 super.checkPermission(AWTPermissions.CHECK_AWT_EVENTQUEUE_PERMISSION); 313 } 314 } // checkAwtEventQueueAccess() 315 316 /** 317 * Returns the thread group of the applet. We consult the classloader 318 * if there is one. 319 */ 320 public ThreadGroup getThreadGroup() { 321 /* If any applet code is on the execution stack, we return 322 that applet's ThreadGroup. Otherwise, we use the default 323 behavior. */ 324 AppletClassLoader appletLoader = currentAppletClassLoader(); 325 ThreadGroup loaderGroup = (appletLoader == null) ? null 326 : appletLoader.getThreadGroup(); 327 if (loaderGroup != null) { 328 return loaderGroup; 329 } else { 330 return super.getThreadGroup(); 331 } 332 } // getThreadGroup() 333 334 /** 335 * Get the AppContext corresponding to the current context. 336 * The default implementation returns null, but this method 337 * may be overridden by various SecurityManagers 338 * (e.g. AppletSecurity) to index AppContext objects by the 339 * calling context. 340 * 341 * @return the AppContext corresponding to the current context. 342 * @see sun.awt.AppContext 343 * @see java.lang.SecurityManager 344 * @since 1.2.1 345 */ 346 public AppContext getAppContext() { 347 AppletClassLoader appletLoader = currentAppletClassLoader(); 348 349 if (appletLoader == null) { 350 return null; 351 } else { 352 AppContext context = appletLoader.getAppContext(); 353 354 // context == null when some thread in applet thread group 355 // has not been destroyed in AppContext.dispose() 356 if (context == null) { 357 throw new SecurityException("Applet classloader has invalid AppContext"); 358 } 359 360 return context; 361 } 362 } 363 364 } // class AppletSecurity