jamvm
view lib/java/security/VMAccessController.java @ 399:2b94bfbe7ec6
Remove ambiguity caused by new CodeSource constructor.
2008-08-04 Andrew John Hughes <gnu_andrew@member.fsf.org>
* lib/java/security/VMAccessController.java:
Remove ambiguity in call to java.security.CodeSource
constructor introduced by recent API changes.
2008-08-04 Andrew John Hughes <gnu_andrew@member.fsf.org>
* lib/java/security/VMAccessController.java:
Remove ambiguity in call to java.security.CodeSource
constructor introduced by recent API changes.
| author | andrew |
|---|---|
| date | Tue Aug 05 04:08:33 2008 +0100 (2008-08-05) |
| parents | 6476eceedae8 |
| children |
line source
1 /* VMAccessController.java -- VM-specific access controller methods.
2 Copyright (C) 2004 Free Software Foundation, Inc.
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2, or (at your option)
7 any later version.
9 This program is distributed in the hope that it will be useful, but
10 WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; see the file COPYING. If not, write to the
16 Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
17 02111-1307 USA.
19 Linking this library statically or dynamically with other modules is
20 making a combined work based on this library. Thus, the terms and
21 conditions of the GNU General Public License cover the whole
22 combination.
24 As a special exception, the copyright holders of this library give you
25 permission to link this library with independent modules to produce an
26 executable, regardless of the license terms of these independent
27 modules, and to copy and distribute the resulting executable under
28 terms of your choice, provided that you also meet, for each linked
29 independent module, the terms and conditions of the license of that
30 module. An independent module is a module which is not derived from
31 or based on this library. If you modify this library, you may extend
32 this exception to your version of the library, but you are not
33 obligated to do so. If you do not wish to do so, delete this
34 exception statement from your version. */
37 package java.security;
39 import java.net.URL;
41 import java.security.cert.Certificate;
43 import java.util.HashSet;
44 import java.util.LinkedList;
46 /**
47 * This version is for JamVM.
48 */
49 final class VMAccessController
50 {
52 // Fields.
53 // -------------------------------------------------------------------------
55 /**
56 * This is a per-thread stack of AccessControlContext objects (which can
57 * be null) for each call to AccessController.doPrivileged in each thread's
58 * call stack. We use this to remember which context object corresponds to
59 * which call.
60 */
61 private static final ThreadLocal contexts = new ThreadLocal();
63 /**
64 * This is a Boolean that, if set, tells getContext that it has already
65 * been called once, allowing us to handle recursive permission checks
66 * caused by methods getContext calls.
67 */
68 private static final ThreadLocal inGetContext = new ThreadLocal();
70 /**
71 * And we return this all-permissive context to ensure that privileged
72 * methods called from getContext succeed.
73 */
74 private final static AccessControlContext DEFAULT_CONTEXT;
75 static
76 {
77 //CodeSource source = new CodeSource(null, null);
78 CodeSource source = new CodeSource((URL) null, (Certificate[]) null);
79 Permissions permissions = new Permissions();
80 permissions.add(new AllPermission());
81 ProtectionDomain[] domain = new ProtectionDomain[] {
82 new ProtectionDomain(source, permissions)
83 };
84 DEFAULT_CONTEXT = new AccessControlContext(domain);
85 }
87 private static final boolean DEBUG = false;
88 private static void debug(String msg)
89 {
90 System.err.print(">>> VMAccessController: ");
91 System.err.println(msg);
92 }
94 // Constructors.
95 // -------------------------------------------------------------------------
97 private VMAccessController() { }
99 // Class methods.
100 // -------------------------------------------------------------------------
102 /**
103 * Relate a class (which should be an instance of {@link PrivilegedAction}
104 * with an access control context. This method is used by {@link
105 * AccessController#doPrivileged(java.security.PrivilegedAction,java.security.AccessControlContext)}
106 * to set up the context that will be returned by {@link #getContext()}.
107 * This method relates the class to the current thread, so contexts
108 * pushed from one thread will not be available to another.
109 *
110 * @param acc The access control context.
111 */
112 static void pushContext (AccessControlContext acc)
113 {
114 if (DEBUG)
115 debug("pushing " + acc);
116 LinkedList stack = (LinkedList) contexts.get();
117 if (stack == null)
118 {
119 stack = new LinkedList();
120 contexts.set(stack);
121 }
122 stack.addFirst(acc);
123 }
125 /**
126 * Removes the relation of a class to an {@link AccessControlContext}.
127 * This method is used by {@link AccessController} when exiting from a
128 * call to {@link
129 * AccessController#doPrivileged(java.security.PrivilegedAction,java.security.AccessControlContext)}.
130 */
131 static void popContext()
132 {
133 if (DEBUG)
134 debug("popping context");
136 // Stack should never be null, nor should it be empty, if this method
137 // and its counterpart has been called properly.
138 LinkedList stack = (LinkedList) contexts.get();
139 if (stack != null)
140 {
141 stack.removeFirst();
142 if (stack.isEmpty())
143 contexts.set(null);
144 }
145 }
147 /**
148 * Examine the method stack of the currently running thread, and create
149 * an {@link AccessControlContext} filled in with the appropriate {@link
150 * ProtectionDomain} objects given this stack.
151 *
152 * @return The context.
153 */
154 static AccessControlContext getContext()
155 {
156 // If we are already in getContext, but called a method that needs
157 // a permission check, return the all-permissive context so methods
158 // called from here succeed.
159 //
160 // XXX is this necessary? We should verify if there are any calls in
161 // the stack below this method that require permission checks.
162 Boolean inCall = (Boolean) inGetContext.get();
163 if (inCall != null && inCall.booleanValue())
164 {
165 if (DEBUG)
166 debug("already in getContext");
167 return DEFAULT_CONTEXT;
168 }
170 inGetContext.set(Boolean.TRUE);
172 Object[][] stack = getStack();
173 Class[] classes = (Class[]) stack[0];
174 String[] methods = (String[]) stack[1];
176 if (DEBUG)
177 debug(">>> got trace of length " + classes.length);
179 HashSet domains = new HashSet();
180 HashSet seenDomains = new HashSet();
181 AccessControlContext context = null;
182 int privileged = 0;
184 // We walk down the stack, adding each ProtectionDomain for each
185 // class in the call stack. If we reach a call to doPrivileged,
186 // we don't add any more stack frames. We skip the first three stack
187 // frames, since they comprise the calls to getStack, getContext,
188 // and AccessController.getContext.
189 for (int i = 3; i < classes.length && privileged < 2; i++)
190 {
191 Class clazz = classes[i];
192 String method = methods[i];
194 if (DEBUG)
195 {
196 debug(">>> checking " + clazz + "." + method);
197 debug(">>> loader = " + clazz.getClassLoader());
198 }
200 // If the previous frame was a call to doPrivileged, then this is
201 // the last frame we look at.
202 if (privileged == 1)
203 privileged = 2;
205 if (clazz.equals (AccessController.class)
206 && method.equals ("doPrivileged"))
207 {
208 // If there was a call to doPrivileged with a supplied context,
209 // return that context.
210 LinkedList l = (LinkedList) contexts.get();
211 if (l != null)
212 context = (AccessControlContext) l.getFirst();
213 privileged = 1;
214 }
216 ProtectionDomain domain = clazz.getProtectionDomain();
218 if (domain == null)
219 continue;
220 if (seenDomains.contains(domain))
221 continue;
222 seenDomains.add(domain);
224 // Create a static snapshot of this domain, which may change over time
225 // if the current policy changes.
226 domains.add(new ProtectionDomain(domain.getCodeSource(),
227 domain.getPermissions()));
228 }
230 if (DEBUG)
231 debug("created domains: " + domains);
233 ProtectionDomain[] result = (ProtectionDomain[])
234 domains.toArray(new ProtectionDomain[domains.size()]);
236 // Intersect the derived protection domain with the context supplied
237 // to doPrivileged.
238 if (context != null)
239 /*
240 Removed to allow building against OpenJDK
241 Andrew John Hughes - July 2008
242 context = new AccessControlContext(result, context,
243 IntersectingDomainCombiner.SINGLETON);
244 */
245 throw new InternalError("Can't intersect context with derived protection domain");
246 // No context was supplied. Return the derived one.
247 else
248 context = new AccessControlContext(result);
250 inGetContext.set(Boolean.FALSE);
251 return context;
252 }
254 /**
255 * Returns a snapshot of the current call stack as a pair of arrays:
256 * the first an array of classes in the call stack, the second an array
257 * of strings containing the method names in the call stack. The two
258 * arrays match up, meaning that method <i>i</i> is declared in class
259 * <i>i</i>. The arrays are clean; it will only contain Java methods,
260 * and no element of the list should be null.
261 *
262 * @return A pair of arrays describing the current call stack. The first
263 * element is an array of Class objects, and the second is an array
264 * of Strings comprising the method names.
265 */
266 private static native Object[][] getStack();
267 }
