001: /* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
002: *
003: * ***** BEGIN LICENSE BLOCK *****
004: * Version: MPL 1.1/GPL 2.0
005: *
006: * The contents of this file are subject to the Mozilla Public License Version
007: * 1.1 (the "License"); you may not use this file except in compliance with
008: * the License. You may obtain a copy of the License at
009: * http://www.mozilla.org/MPL/
010: *
011: * Software distributed under the License is distributed on an "AS IS" basis,
012: * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
013: * for the specific language governing rights and limitations under the
014: * License.
015: *
016: * The Original Code is Rhino code, released
017: * May 6, 1999.
018: *
019: * The Initial Developer of the Original Code is
020: * Netscape Communications Corporation.
021: * Portions created by the Initial Developer are Copyright (C) 1997-1999
022: * the Initial Developer. All Rights Reserved.
023: *
024: * Contributor(s):
025: * Norris Boyd
026: * Igor Bukanov
027: *
028: * Alternatively, the contents of this file may be used under the terms of
029: * the GNU General Public License Version 2 or later (the "GPL"), in which
030: * case the provisions of the GPL are applicable instead of those above. If
031: * you wish to allow use of your version of this file only under the terms of
032: * the GPL and not to allow others to use your version of this file under the
033: * MPL, indicate your decision by deleting the provisions above and replacing
034: * them with the notice and other provisions required by the GPL. If you do
035: * not delete the provisions above, a recipient may use your version of this
036: * file under either the MPL or the GPL.
037: *
038: * ***** END LICENSE BLOCK ***** */
039:
040: // API class
041: package org.mozilla.javascript;
042:
043: /**
044: * This class describes the support needed to implement security.
045: * <p>
046: * Three main pieces of functionality are required to implement
047: * security for JavaScript. First, it must be possible to define
048: * classes with an associated security domain. (This security
049: * domain may be any object incorporating notion of access
050: * restrictions that has meaning to an embedding; for a client-side
051: * JavaScript embedding this would typically be
052: * java.security.ProtectionDomain or similar object depending on an
053: * origin URL and/or a digital certificate.)
054: * Next it must be possible to get a security domain object that
055: * allows a particular action only if all security domains
056: * associated with code on the current Java stack allows it. And
057: * finally, it must be possible to execute script code with
058: * associated security domain injected into Java stack.
059: * <p>
060: * These three pieces of functionality are encapsulated in the
061: * SecurityController class.
062: *
063: * @see org.mozilla.javascript.Context#setSecurityController(SecurityController)
064: * @see java.lang.ClassLoader
065: * @since 1.5 Release 4
066: */
067: public abstract class SecurityController {
068: private static SecurityController global;
069:
070: // The method must NOT be public or protected
071: static SecurityController global() {
072: return global;
073: }
074:
075: /**
076: * Check if global {@link SecurityController} was already installed.
077: * @see #initGlobal(SecurityController controller)
078: */
079: public static boolean hasGlobal() {
080: return global != null;
081: }
082:
083: /**
084: * Initialize global controller that will be used for all
085: * security-related operations. The global controller takes precedence
086: * over already installed {@link Context}-specific controllers and cause
087: * any subsequent call to
088: * {@link Context#setSecurityController(SecurityController)}
089: * to throw an exception.
090: * <p>
091: * The method can only be called once.
092: *
093: * @see #hasGlobal()
094: */
095: public static void initGlobal(SecurityController controller) {
096: if (controller == null)
097: throw new IllegalArgumentException();
098: if (global != null) {
099: throw new SecurityException(
100: "Cannot overwrite already installed global SecurityController");
101: }
102: global = controller;
103: }
104:
105: /**
106: * Get class loader-like object that can be used
107: * to define classes with the given security context.
108: * @param parentLoader parent class loader to delegate search for classes
109: * not defined by the class loader itself
110: * @param securityDomain some object specifying the security
111: * context of the code that is defined by the returned class loader.
112: */
113: public abstract GeneratedClassLoader createClassLoader(
114: ClassLoader parentLoader, Object securityDomain);
115:
116: /**
117: * Create {@link GeneratedClassLoader} with restrictions imposed by
118: * staticDomain and all current stack frames.
119: * The method uses the SecurityController instance associated with the
120: * current {@link Context} to construct proper dynamic domain and create
121: * corresponding class loader.
122: * <par>
123: * If no SecurityController is associated with the current {@link Context} ,
124: * the method calls {@link Context#createClassLoader(ClassLoader parent)}.
125: *
126: * @param parent parent class loader. If null,
127: * {@link Context#getApplicationClassLoader()} will be used.
128: * @param staticDomain static security domain.
129: */
130: public static GeneratedClassLoader createLoader(ClassLoader parent,
131: Object staticDomain) {
132: Context cx = Context.getContext();
133: if (parent == null) {
134: parent = cx.getApplicationClassLoader();
135: }
136: SecurityController sc = cx.getSecurityController();
137: GeneratedClassLoader loader;
138: if (sc == null) {
139: loader = cx.createClassLoader(parent);
140: } else {
141: Object dynamicDomain = sc
142: .getDynamicSecurityDomain(staticDomain);
143: loader = sc.createClassLoader(parent, dynamicDomain);
144: }
145: return loader;
146: }
147:
148: public static Class getStaticSecurityDomainClass() {
149: SecurityController sc = Context.getContext()
150: .getSecurityController();
151: return sc == null ? null : sc
152: .getStaticSecurityDomainClassInternal();
153: }
154:
155: public Class getStaticSecurityDomainClassInternal() {
156: return null;
157: }
158:
159: /**
160: * Get dynamic security domain that allows an action only if it is allowed
161: * by the current Java stack and <i>securityDomain</i>. If
162: * <i>securityDomain</i> is null, return domain representing permissions
163: * allowed by the current stack.
164: */
165: public abstract Object getDynamicSecurityDomain(
166: Object securityDomain);
167:
168: /**
169: * Call {@link
170: * Callable#call(Context cx, Scriptable scope, Scriptable thisObj,
171: * Object[] args)}
172: * of <i>callable</i> under restricted security domain where an action is
173: * allowed only if it is allowed according to the Java stack on the
174: * moment of the <i>execWithDomain</i> call and <i>securityDomain</i>.
175: * Any call to {@link #getDynamicSecurityDomain(Object)} during
176: * execution of <tt>callable.call(cx, scope, thisObj, args)</tt>
177: * should return a domain incorporate restrictions imposed by
178: * <i>securityDomain</i> and Java stack on the moment of callWithDomain
179: * invocation.
180: * <p>
181: * The method should always be overridden, it is not declared abstract
182: * for compatibility reasons.
183: */
184: public Object callWithDomain(Object securityDomain, Context cx,
185: final Callable callable, Scriptable scope,
186: final Scriptable this Obj, final Object[] args) {
187: return execWithDomain(cx, scope, new Script() {
188: public Object exec(Context cx, Scriptable scope) {
189: return callable.call(cx, scope, this Obj, args);
190: }
191:
192: }, securityDomain);
193: }
194:
195: /**
196: * @deprecated The application should not override this method and instead
197: * override
198: * {@link #callWithDomain(Object securityDomain, Context cx, Callable callable, Scriptable scope, Scriptable thisObj, Object[] args)}.
199: */
200: public Object execWithDomain(Context cx, Scriptable scope,
201: Script script, Object securityDomain) {
202: throw new IllegalStateException(
203: "callWithDomain should be overridden");
204: }
205:
206: }
|