blob: 61a33a58482b841e9842f4a508c5613876aa8654 [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25
26package com.sun.script.javascript;
27
28import java.lang.reflect.*;
29import static sun.security.util.SecurityConstants.*;
30import sun.org.mozilla.javascript.internal.*;
31
32/**
33 * This wrap factory is used for security reasons. JSR 223 script
34 * engine interface and JavaScript engine classes are run as bootstrap
35 * classes. For example, java.lang.Class.forName method (when called without
36 * class loader) uses caller's class loader. This may be exploited by script
37 * authors to access classes otherwise not accessible. For example,
38 * classes in sun.* namespace are normally not accessible to untrusted
39 * code and hence should not be accessible to JavaScript run from
40 * untrusted code.
41 *
42 * @author A. Sundararajan
43 * @since 1.6
44 */
45final class RhinoWrapFactory extends WrapFactory {
46 private RhinoWrapFactory() {}
47 private static RhinoWrapFactory theInstance;
48
49 static synchronized WrapFactory getInstance() {
50 if (theInstance == null) {
51 theInstance = new RhinoWrapFactory();
52 }
53 return theInstance;
54 }
55
56 // We use instance of this class to wrap security sensitive
57 // Java object. Please refer below.
58 private static class RhinoJavaObject extends NativeJavaObject {
59 RhinoJavaObject(Scriptable scope, Object obj, Class type) {
60 // we pass 'null' to object. NativeJavaObject uses
61 // passed 'type' to reflect fields and methods when
62 // object is null.
63 super(scope, null, type);
64
65 // Now, we set actual object. 'javaObject' is protected
66 // field of NativeJavaObject.
67 javaObject = obj;
68 }
69 }
70
71 public Scriptable wrapAsJavaObject(Context cx, Scriptable scope,
72 Object javaObject, Class staticType) {
73 SecurityManager sm = System.getSecurityManager();
74 ClassShutter classShutter = RhinoClassShutter.getInstance();
75 if (javaObject instanceof ClassLoader) {
76 // Check with Security Manager whether we can expose a
77 // ClassLoader...
78 if (sm != null) {
79 sm.checkPermission(GET_CLASSLOADER_PERMISSION);
80 }
81 // if we fall through here, check permission succeeded.
82 return super.wrapAsJavaObject(cx, scope, javaObject, staticType);
83 } else {
84 String name = null;
85 if (javaObject instanceof Class) {
86 name = ((Class)javaObject).getName();
87 } else if (javaObject instanceof Member) {
88 Member member = (Member) javaObject;
89 // Check member access. Don't allow reflective access to
90 // non-public members. Note that we can't call checkMemberAccess
91 // because that expects exact stack depth!
92 if (sm != null && !Modifier.isPublic(member.getModifiers())) {
93 return null;
94 }
95 name = member.getDeclaringClass().getName();
96 }
97 // Now, make sure that no ClassShutter prevented Class or Member
98 // of it is accessed reflectively. Note that ClassShutter may
99 // prevent access to a class, even though SecurityManager permit.
100 if (name != null) {
101 if (!classShutter.visibleToScripts(name)) {
102 return null;
103 } else {
104 return super.wrapAsJavaObject(cx, scope, javaObject, staticType);
105 }
106 }
107 }
108
109 // we have got some non-reflective object.
110 Class dynamicType = javaObject.getClass();
111 String name = dynamicType.getName();
112 if (!classShutter.visibleToScripts(name)) {
113 // Object of some sensitive class (such as sun.net.www.*
114 // objects returned from public method of java.net.URL class.
115 // We expose this object as though it is an object of some
116 // super class that is safe for access.
117
118 Class type = null;
119
120 // Whenever a Java Object is wrapped, we are passed with a
121 // staticType which is the type found from environment. For
122 // example, method return type known from signature. The dynamic
123 // type would be the actual Class of the actual returned object.
124 // If the staticType is an interface, we just use that type.
125 if (staticType != null && staticType.isInterface()) {
126 type = staticType;
127 } else {
128 // dynamicType is always a class type and never an interface.
129 // find an accessible super class of the dynamic type.
130 while (dynamicType != null) {
131 dynamicType = dynamicType.getSuperclass();
132 name = dynamicType.getName();
133 if (classShutter.visibleToScripts(name)) {
134 type = dynamicType; break;
135 }
136 }
137 // atleast java.lang.Object has to be accessible. So, when
138 // we reach here, type variable should not be null.
139 assert type != null:
140 "even java.lang.Object is not accessible?";
141 }
142 // create custom wrapper with the 'safe' type.
143 return new RhinoJavaObject(scope, javaObject, type);
144 } else {
145 return super.wrapAsJavaObject(cx, scope, javaObject, staticType);
146 }
147 }
148}