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 private AppletClassLoader currentAppletClassLoader() 114 { 115 // try currentClassLoader first 116 ClassLoader loader = currentClassLoader(); 117 118 if ((loader == null) || (loader instanceof AppletClassLoader)) 119 return (AppletClassLoader)loader; 120 121 // if that fails, get all the classes on the stack and check them. 122 Class<?>[] context = getClassContext(); 123 for (int i = 0; i < context.length; i++) { 124 loader = context[i].getClassLoader(); 125 if (loader instanceof AppletClassLoader) 126 return (AppletClassLoader)loader; 127 } 128 129 /* 130 * fix bug # 6433620 the logic here is : try to find URLClassLoader from 131 * class context, check its AccessControlContext to see if 132 * AppletClassLoader is in stack when it's created. for this kind of 133 * URLClassLoader, return the AppContext associated with the 134 * AppletClassLoader. 135 */ 136 for (int i = 0; i < context.length; i++) { 137 final ClassLoader currentLoader = context[i].getClassLoader(); 138 139 if (currentLoader instanceof URLClassLoader) { 140 URLClassLoader ld = (URLClassLoader)currentLoader; 141 loader = AccessController.doPrivileged( 142 new PrivilegedAction<ClassLoader>() { 143 public ClassLoader run() { 144 145 AccessControlContext acc = null; 146 ProtectionDomain[] pds = null; 147 148 try { 149 acc = JNUCLA.getAccessControlContext(ld); 150 if (acc == null) { 151 return null; 152 } 153 154 pds = JSA.getProtectDomains(acc); 155 if (pds == null) { 156 return null; 157 } 158 } catch (Exception e) { 159 throw new UnsupportedOperationException(e); 160 } 161 162 for (int i=0; i<pds.length; i++) { 163 ClassLoader cl = pds[i].getClassLoader(); 164 165 if (cl instanceof AppletClassLoader) { 166 return cl; 167 } 168 } 169 170 return null; 171 } 172 }); 173 174 if (loader != null) { 175 return (AppletClassLoader) loader; 176 } 177 } 178 } 179 180 // if that fails, try the context class loader 181 loader = Thread.currentThread().getContextClassLoader(); 182 if (loader instanceof AppletClassLoader) 183 return (AppletClassLoader)loader; 184 185 // no AppletClassLoaders on the stack 186 return (AppletClassLoader)null; 187 } 188 189 /** 190 * Returns true if this threadgroup is in the applet's own thread 191 * group. This will return false if there is no current class 192 * loader. 193 */ 194 protected boolean inThreadGroup(ThreadGroup g) { 195 if (currentAppletClassLoader() == null) 196 return false; 197 else 198 return getThreadGroup().parentOf(g); 199 } 200 201 /** 202 * Returns true of the threadgroup of thread is in the applet's 203 * own threadgroup. 204 */ 205 protected boolean inThreadGroup(Thread thread) { 206 return inThreadGroup(thread.getThreadGroup()); 207 } 208 209 /** 210 * Applets are not allowed to manipulate threads outside 211 * applet thread groups. However a terminated thread no longer belongs 212 * to any group. 213 */ 214 public void checkAccess(Thread t) { 215 /* When multiple applets is reloaded simultaneously, there will be 216 * multiple invocations to this method from plugin's SecurityManager. 217 * This method should not be synchronized to avoid deadlock when 218 * a page with multiple applets is reloaded 219 */ 220 if ((t.getState() != Thread.State.TERMINATED) && !inThreadGroup(t)) { 221 checkPermission(SecurityConstants.MODIFY_THREAD_PERMISSION); 222 } 223 } 224 225 private boolean inThreadGroupCheck = false; 226 227 /** 228 * Applets are not allowed to manipulate thread groups outside 229 * applet thread groups. 230 */ 231 public synchronized void checkAccess(ThreadGroup g) { 232 if (inThreadGroupCheck) { 233 // if we are in a recursive check, it is because 234 // inThreadGroup is calling appletLoader.getThreadGroup 235 // in that case, only do the super check, as appletLoader 236 // has a begin/endPrivileged 237 checkPermission(SecurityConstants.MODIFY_THREADGROUP_PERMISSION); 238 } else { 239 try { 240 inThreadGroupCheck = true; 241 if (!inThreadGroup(g)) { 242 checkPermission(SecurityConstants.MODIFY_THREADGROUP_PERMISSION); 243 } 244 } finally { 245 inThreadGroupCheck = false; 246 } 247 } 248 } 249 250 251 /** 252 * Throws a {@code SecurityException} if the 253 * calling thread is not allowed to access the package specified by 254 * the argument. 255 * <p> 256 * This method is used by the {@code loadClass} method of class 257 * loaders. 258 * <p> 259 * The {@code checkPackageAccess} method for class 260 * {@code SecurityManager} calls 261 * {@code checkPermission} with the 262 * {@code RuntimePermission("accessClassInPackage."+ pkgname)} 263 * permission. 264 * 265 * @param pkgname the package name. 266 * @exception SecurityException if the caller does not have 267 * permission to access the specified package. 268 * @see java.lang.ClassLoader#loadClass(java.lang.String, boolean) 269 */ 270 public void checkPackageAccess(final String pkgname) { 271 272 // first see if the VM-wide policy allows access to this package 273 super.checkPackageAccess(pkgname); 274 275 // now check the list of restricted packages 276 for (Iterator<String> iter = restrictedPackages.iterator(); iter.hasNext();) 277 { 278 String pkg = iter.next(); 279 280 // Prevent matching "sun" and "sunir" even if they 281 // starts with similar beginning characters 282 // 283 if (pkgname.equals(pkg) || pkgname.startsWith(pkg + ".")) 284 { 285 checkPermission(new java.lang.RuntimePermission 286 ("accessClassInPackage." + pkgname)); 287 } 288 } 289 } 290 291 /** 292 * Tests if a client can get access to the AWT event queue. 293 * <p> 294 * This method calls {@code checkPermission} with the 295 * {@code AWTPermission("accessEventQueue")} permission. 296 * 297 * @since 1.1 298 * @exception SecurityException if the caller does not have 299 * permission to access the AWT event queue. 300 */ 301 @SuppressWarnings("deprecation") 302 public void checkAwtEventQueueAccess() { 303 AppContext appContext = AppContext.getAppContext(); 304 AppletClassLoader appletClassLoader = currentAppletClassLoader(); 305 306 if (AppContext.isMainContext(appContext) && (appletClassLoader != null)) { 307 // If we're about to allow access to the main EventQueue, 308 // and anything untrusted is on the class context stack, 309 // disallow access. 310 super.checkPermission(AWTPermissions.CHECK_AWT_EVENTQUEUE_PERMISSION); 311 } 312 } // checkAwtEventQueueAccess() 313 314 /** 315 * Returns the thread group of the applet. We consult the classloader 316 * if there is one. 317 */ 318 public ThreadGroup getThreadGroup() { 319 /* If any applet code is on the execution stack, we return 320 that applet's ThreadGroup. Otherwise, we use the default 321 behavior. */ 322 AppletClassLoader appletLoader = currentAppletClassLoader(); 323 ThreadGroup loaderGroup = (appletLoader == null) ? null 324 : appletLoader.getThreadGroup(); 325 if (loaderGroup != null) { 326 return loaderGroup; 327 } else { 328 return super.getThreadGroup(); 329 } 330 } // getThreadGroup() 331 332 /** 333 * Get the AppContext corresponding to the current context. 334 * The default implementation returns null, but this method 335 * may be overridden by various SecurityManagers 336 * (e.g. AppletSecurity) to index AppContext objects by the 337 * calling context. 338 * 339 * @return the AppContext corresponding to the current context. 340 * @see sun.awt.AppContext 341 * @see java.lang.SecurityManager 342 * @since 1.2.1 343 */ 344 public AppContext getAppContext() { 345 AppletClassLoader appletLoader = currentAppletClassLoader(); 346 347 if (appletLoader == null) { 348 return null; 349 } else { 350 AppContext context = appletLoader.getAppContext(); 351 352 // context == null when some thread in applet thread group 353 // has not been destroyed in AppContext.dispose() 354 if (context == null) { 355 throw new SecurityException("Applet classloader has invalid AppContext"); 356 } 357 358 return context; 359 } 360 } 361 362 } // class AppletSecurity