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