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