View Javadoc
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.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 associated 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 access 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