001: /*
002: * @(#)XletSecurity.java 1.6 06/10/10
003: *
004: * Copyright 1990-2006 Sun Microsystems, Inc. All Rights Reserved.
005: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
006: *
007: * This program is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU General Public License version
009: * 2 only, as published by the Free Software Foundation.
010: *
011: * This program is distributed in the hope that it will be useful, but
012: * WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * General Public License version 2 for more details (a copy is
015: * included at /legal/license.txt).
016: *
017: * You should have received a copy of the GNU General Public License
018: * version 2 along with this work; if not, write to the Free Software
019: * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA
021: *
022: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
023: * Clara, CA 95054 or visit www.sun.com if you need additional
024: * information or have any questions.
025: */
026:
027: package com.sun.xlet;
028:
029: import java.io.File;
030: import java.io.FilePermission;
031: import java.io.IOException;
032: import java.io.FileDescriptor;
033: import java.net.URL;
034: import java.net.InetAddress;
035: import java.net.UnknownHostException;
036: import java.net.SocketPermission;
037: import java.util.Enumeration;
038: import java.util.Iterator;
039: import java.util.HashSet;
040: import java.util.StringTokenizer;
041: import java.security.*;
042: import sun.awt.AWTSecurityManager;
043: import sun.awt.AppContext;
044: import sun.security.provider.*;
045: import sun.security.util.SecurityConstants;
046:
047: /**
048: * This class defines an xlet security policy
049: *
050: * @version 1.109, 01/23/03
051: */
052: public class XletSecurity extends AWTSecurityManager {
053: private AppContext mainAppContext;
054:
055: /**
056: * Construct and initialize.
057: */
058: public XletSecurity() {
059: this (AppContext.getAppContext());
060: }
061:
062: public XletSecurity(AppContext appContext) {
063: // reset(); see reset().
064: mainAppContext = appContext;
065: }
066:
067: // Cache to store known restricted packages
068: private HashSet restrictedPackages = new HashSet();
069:
070: /**
071: * Reset from Properties
072: *
073: * this method exists to set additional package
074: * access restrictions, which in Applet's case provided
075: * in $USER/.appletviewer or $USER/.hotjava/properties file
076: * as "package.restrict.access.<pkgname>, * <true | false>".
077: * Xlets don't have this default property file, but I'm
078: * leaving the method for now and commenting out the call
079: * from the constructor.
080: */
081: public void reset() {
082: // Clear cache
083: restrictedPackages.clear();
084:
085: AccessController.doPrivileged(new PrivilegedAction() {
086: public Object run() {
087: // Enumerate system properties
088: Enumeration e = System.getProperties().propertyNames();
089:
090: while (e.hasMoreElements()) {
091: String name = (String) e.nextElement();
092:
093: if (name != null
094: && name
095: .startsWith("package.restrict.access.")) {
096: String value = System.getProperty(name);
097:
098: if (value != null
099: && value.equalsIgnoreCase("true")) {
100: String pkg = name.substring(24);
101:
102: // Cache restricted packages
103: restrictedPackages.add(pkg);
104: }
105: }
106: }
107: return null;
108: }
109: });
110: }
111:
112: /**
113: * get the current (first) instance of an XletClassLoader on the stack.
114: */
115: private XletClassLoader currentXletClassLoader() {
116: /**
117: // try currentClassLoader first
118: ClassLoader loader = currentClassLoader();
119: if ((loader == null) || (loader instanceof XletClassLoader))
120: return (XletClassLoader)loader;
121: **/
122: ClassLoader loader;
123:
124: // if that fails, get all the classes on the stack and check them.
125: Class[] context = getClassContext();
126: for (int i = 0; i < context.length; i++) {
127: loader = context[i].getClassLoader();
128: if (loader instanceof XletClassLoader)
129: return (XletClassLoader) loader;
130: }
131:
132: // if that fails, try the context class loader
133: loader = Thread.currentThread().getContextClassLoader();
134: if (loader instanceof XletClassLoader)
135: return (XletClassLoader) loader;
136:
137: // no XletClassLoaders on the stack
138: return (XletClassLoader) null;
139: }
140:
141: /**
142: * Returns true if this threadgroup is in the xlet's own thread
143: * group. This will return false if there is no current class
144: * loader.
145: */
146: protected boolean inThreadGroup(ThreadGroup g) {
147: if (currentXletClassLoader() != null)
148: return getThreadGroup().parentOf(g);
149:
150: return false;
151: }
152:
153: /**
154: * Returns true of the threadgroup of thread is in the xlet's
155: * own threadgroup.
156: */
157: protected boolean inThreadGroup(Thread thread) {
158: return inThreadGroup(thread.getThreadGroup());
159: }
160:
161: /**
162: * Xlets are not allowed to manipulate threads outside
163: * xlet thread groups.
164: */
165: public synchronized void checkAccess(Thread t) {
166: if (!inThreadGroup(t)) {
167: checkPermission(SecurityConstants.MODIFY_THREAD_PERMISSION);
168: }
169: }
170:
171: private boolean inThreadGroupCheck = false;
172:
173: /**
174: * Xlets are not allowed to manipulate thread groups outside
175: * xlet thread groups.
176: */
177: public synchronized void checkAccess(ThreadGroup g) {
178: if (inThreadGroupCheck) {
179: // if we are in a recursive check, it is because
180: // inThreadGroup is calling xletLoader.getThreadGroup
181: // in that case, only do the super check, as xletLoader
182: // has a begin/endPrivileged
183: checkPermission(SecurityConstants.MODIFY_THREADGROUP_PERMISSION);
184: } else {
185: try {
186: inThreadGroupCheck = true;
187: if (!inThreadGroup(g)) {
188: checkPermission(SecurityConstants.MODIFY_THREADGROUP_PERMISSION);
189: }
190: } finally {
191: inThreadGroupCheck = false;
192: }
193: }
194: }
195:
196: /**
197: * Throws a <code>SecurityException</code> if the
198: * calling thread is not allowed to access the package specified by
199: * the argument.
200: * <p>
201: * This method is used by the <code>loadClass</code> method of class
202: * loaders.
203: * <p>
204: * The <code>checkPackageAccess</code> method for class
205: * <code>SecurityManager</code> calls
206: * <code>checkPermission</code> with the
207: * <code>RuntimePermission("accessClassInPackage."+pkg)</code>
208: * permission.
209: *
210: * @param pkg the package name.
211: * @exception SecurityException if the caller does not have
212: * permission to access the specified package.
213: * @see java.lang.ClassLoader#loadClass(java.lang.String, boolean)
214: */
215: public void checkPackageAccess(final String pkgname) {
216:
217: // first see if the VM-wide policy allows access to this package
218: super .checkPackageAccess(pkgname);
219:
220: // now check the list of restricted packages
221: for (Iterator iter = restrictedPackages.iterator(); iter
222: .hasNext();) {
223: String pkg = (String) iter.next();
224:
225: // Prevent matching "sun" and "sunir" even if they
226: // starts with similar beginning characters
227: //
228: if (pkgname.equals(pkg) || pkgname.startsWith(pkg + ".")) {
229: checkPermission(new java.lang.RuntimePermission(
230: "accessClassInPackage." + pkgname));
231: }
232: }
233: }
234:
235: /**
236: * Tests if a client can get access to the AWT event queue.
237: * <p>
238: * This method calls <code>checkPermission</code> with the
239: * <code>AWTPermission("accessEventQueue")</code> permission.
240: *
241: * @since JDK1.1
242: * @exception SecurityException if the caller does not have
243: * permission to accesss the AWT event queue.
244: */
245: public void checkAwtEventQueueAccess() {
246: AppContext appContext = AppContext.getAppContext();
247: XletClassLoader xletClassLoader = currentXletClassLoader();
248:
249: if ((appContext == mainAppContext) && (xletClassLoader != null)) {
250: // If we're about to allow access to the main EventQueue,
251: // and anything untrusted is on the class context stack,
252: // disallow access.
253: super .checkAwtEventQueueAccess();
254: }
255: } // checkAwtEventQueueAccess()
256:
257: /**
258: * Returns the thread group of the xlet. We consult the classloader
259: * if there is one.
260: */
261: public ThreadGroup getThreadGroup() {
262: /* If any xlet code is on the execution stack, we return
263: that xlet's ThreadGroup. Otherwise, we use the default
264: behavior. */
265: XletClassLoader xletLoader = currentXletClassLoader();
266: ThreadGroup loaderGroup = (xletLoader == null) ? null
267: : xletLoader.getThreadGroup();
268: if (loaderGroup != null) {
269: return loaderGroup;
270: } else {
271: return super .getThreadGroup();
272: }
273: } // getThreadGroup()
274:
275: /**
276: * Get the AppContext corresponding to the current context.
277: * The default implementation returns null, but this method
278: * may be overridden by various SecurityManagers
279: * (e.g. XletSecurity) to index AppContext objects by the
280: * calling context.
281: *
282: * @return the AppContext corresponding to the current context.
283: * @see sun.awt.AppContext
284: * @see java.lang.SecurityManager
285: * @since JDK1.2.1
286: */
287: public AppContext getAppContext() {
288: XletClassLoader xletLoader = currentXletClassLoader();
289: return (xletLoader == null) ? null : xletLoader.getAppContext();
290: }
291:
292: } // class XletSecurity
|