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