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