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