Source Code Cross Referenced for AccessControlContext.java in  » 6.0-JDK-Core » security » java » security » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Home
Java Source Code / Java Documentation
1.6.0 JDK Core
2.6.0 JDK Modules
3.6.0 JDK Modules com.sun
4.6.0 JDK Modules com.sun.java
5.6.0 JDK Modules sun
6.6.0 JDK Platform
7.Ajax
8.Apache Harmony Java SE
9.Aspect oriented
10.Authentication Authorization
11.Blogger System
12.Build
13.Byte Code
14.Cache
15.Chart
16.Chat
17.Code Analyzer
18.Collaboration
19.Content Management System
20.Database Client
21.Database DBMS
22.Database JDBC Connection Pool
23.Database ORM
24.Development
25.EJB Server
26.ERP CRM Financial
27.ESB
28.Forum
29.Game
30.GIS
31.Graphic 3D
32.Graphic Library
33.Groupware
34.HTML Parser
35.IDE
36.IDE Eclipse
37.IDE Netbeans
38.Installer
39.Internationalization Localization
40.Inversion of Control
41.Issue Tracking
42.J2EE
43.J2ME
44.JBoss
45.JMS
46.JMX
47.Library
48.Mail Clients
49.Music
50.Net
51.Parser
52.PDF
53.Portal
54.Profiler
55.Project Management
56.Report
57.RSS RDF
58.Rule Engine
59.Science
60.Scripting
61.Search Engine
62.Security
63.Sevlet Container
64.Source Control
65.Swing Library
66.Template Engine
67.Test Coverage
68.Testing
69.UML
70.Web Crawler
71.Web Framework
72.Web Mail
73.Web Server
74.Web Services
75.Web Services apache cxf 2.2.6
76.Web Services AXIS2
77.Wiki Engine
78.Workflow Engines
79.XML
80.XML UI
Java Source Code / Java Documentation » 6.0 JDK Core » security » java.security 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001        /*
002         * Copyright 1997-2006 Sun Microsystems, Inc.  All Rights Reserved.
003         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004         *
005         * This code is free software; you can redistribute it and/or modify it
006         * under the terms of the GNU General Public License version 2 only, as
007         * published by the Free Software Foundation.  Sun designates this
008         * particular file as subject to the "Classpath" exception as provided
009         * by Sun in the LICENSE file that accompanied this code.
010         *
011         * This code is distributed in the hope that it will be useful, but WITHOUT
012         * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013         * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
014         * version 2 for more details (a copy is included in the LICENSE file that
015         * accompanied this code).
016         *
017         * You should have received a copy of the GNU General Public License version
018         * 2 along with this work; if not, write to the Free Software Foundation,
019         * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020         *
021         * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022         * CA 95054 USA or visit www.sun.com if you need additional information or
023         * have any questions.
024         */
025
026        package java.security;
027
028        import java.util.ArrayList;
029        import java.util.List;
030        import sun.security.util.Debug;
031        import sun.security.util.SecurityConstants;
032
033        /** 
034         * An AccessControlContext is used to make system resource access decisions
035         * based on the context it encapsulates.
036         * 
037         * <p>More specifically, it encapsulates a context and
038         * has a single method, <code>checkPermission</code>,
039         * that is equivalent to the <code>checkPermission</code> method
040         * in the AccessController class, with one difference: The AccessControlContext
041         * <code>checkPermission</code> method makes access decisions based on the 
042         * context it encapsulates,
043         * rather than that of the current execution thread.
044         * 
045         * <p>Thus, the purpose of AccessControlContext is for those situations where
046         * a security check that should be made within a given context
047         * actually needs to be done from within a
048         * <i>different</i> context (for example, from within a worker thread).
049         * 
050         * <p> An AccessControlContext is created by calling the 
051         * <code>AccessController.getContext</code> method. 
052         * The <code>getContext</code> method takes a "snapshot"
053         * of the current calling context, and places
054         * it in an AccessControlContext object, which it returns. A sample call is
055         * the following:
056         * 
057         * <pre>
058         *   AccessControlContext acc = AccessController.getContext()
059         * </pre>
060         * 
061         * <p>
062         * Code within a different context can subsequently call the
063         * <code>checkPermission</code> method on the
064         * previously-saved AccessControlContext object. A sample call is the
065         * following:
066         * 
067         * <pre>
068         *   acc.checkPermission(permission)
069         * </pre> 
070         * 
071         * @see AccessController
072         *
073         * @author Roland Schemers
074         */
075
076        public final class AccessControlContext {
077
078            private ProtectionDomain context[];
079            private boolean isPrivileged;
080            private AccessControlContext privilegedContext;
081            private DomainCombiner combiner = null;
082
083            private static boolean debugInit = false;
084            private static Debug debug = null;
085
086            static Debug getDebug() {
087                if (debugInit)
088                    return debug;
089                else {
090                    if (Policy.isSet()) {
091                        debug = Debug.getInstance("access");
092                        debugInit = true;
093                    }
094                    return debug;
095                }
096            }
097
098            /**
099             * Create an AccessControlContext with the given set of ProtectionDomains.
100             * Context must not be null. Duplicate domains will be removed from the
101             * context.
102             *
103             * @param context the ProtectionDomains associated with this context.
104             * The non-duplicate domains are copied from the array. Subsequent
105             * changes to the array will not affect this AccessControlContext.
106             */
107            public AccessControlContext(ProtectionDomain context[]) {
108                if (context.length == 0) {
109                    this .context = null;
110                } else if (context.length == 1) {
111                    if (context[0] != null) {
112                        this .context = (ProtectionDomain[]) context.clone();
113                    } else {
114                        this .context = null;
115                    }
116                } else {
117                    List<ProtectionDomain> v = new ArrayList<ProtectionDomain>(
118                            context.length);
119                    for (int i = 0; i < context.length; i++) {
120                        if ((context[i] != null) && (!v.contains(context[i])))
121                            v.add(context[i]);
122                    }
123                    this .context = new ProtectionDomain[v.size()];
124                    this .context = (ProtectionDomain[]) v.toArray(this .context);
125                }
126            }
127
128            /**
129             * Create a new <code>AccessControlContext</code> with the given
130             * <code>AccessControlContext</code> and <code>DomainCombiner</code>.
131             * This constructor associates the provided
132             * <code>DomainCombiner</code> with the provided
133             * <code>AccessControlContext</code>.
134             *
135             * <p>
136             *
137             * @param acc the <code>AccessControlContext</code> associated
138             *		with the provided <code>DomainCombiner</code>.
139             *
140             * @param combiner the <code>DomainCombiner</code> to be associated
141             *		with the provided <code>AccessControlContext</code>.
142             *
143             * @exception NullPointerException if the provided
144             *		<code>context</code> is <code>null</code>.
145             *
146             * @exception SecurityException if a security manager is installed and the 
147             *		caller does not have the "createAccessControlContext" 
148             *		{@link SecurityPermission}
149             * @since 1.3
150             */
151            public AccessControlContext(AccessControlContext acc,
152                    DomainCombiner combiner) {
153
154                SecurityManager sm = System.getSecurityManager();
155                if (sm != null) {
156                    sm.checkPermission(SecurityConstants.CREATE_ACC_PERMISSION);
157                }
158
159                this .context = acc.context;
160
161                // we do not need to run the combine method on the
162                // provided ACC.  it was already "combined" when the
163                // context was originally retrieved.
164                //
165                // at this point in time, we simply throw away the old
166                // combiner and use the newly provided one.
167                this .combiner = combiner;
168            }
169
170            /**
171             * package private for AccessController
172             */
173            AccessControlContext(ProtectionDomain context[],
174                    DomainCombiner combiner) {
175                if (context != null) {
176                    this .context = (ProtectionDomain[]) context.clone();
177                }
178                this .combiner = combiner;
179            }
180
181            /**
182             * package private constructor for AccessController.getContext()
183             */
184
185            AccessControlContext(ProtectionDomain context[],
186                    boolean isPrivileged) {
187                this .context = context;
188                this .isPrivileged = isPrivileged;
189            }
190
191            /**
192             * Returns true if this context is privileged.
193             */
194            boolean isPrivileged() {
195                return isPrivileged;
196            }
197
198            /**
199             * get the assigned combiner from the privileged or inherited context
200             */
201            DomainCombiner getAssignedCombiner() {
202                AccessControlContext acc;
203                if (isPrivileged) {
204                    acc = privilegedContext;
205                } else {
206                    acc = AccessController.getInheritedAccessControlContext();
207                }
208                if (acc != null) {
209                    return acc.combiner;
210                }
211                return null;
212            }
213
214            /**
215             * Get the <code>DomainCombiner</code> associated with this
216             * <code>AccessControlContext</code>.
217             *
218             * <p>
219             *
220             * @return the <code>DomainCombiner</code> associated with this
221             *		<code>AccessControlContext</code>, or <code>null</code>
222             *		if there is none.
223             *
224             * @exception SecurityException if a security manager is installed and
225             *		the caller does not have the "getDomainCombiner"
226             *		{@link SecurityPermission}
227             * @since 1.3
228             */
229            public DomainCombiner getDomainCombiner() {
230
231                SecurityManager sm = System.getSecurityManager();
232                if (sm != null) {
233                    sm
234                            .checkPermission(SecurityConstants.GET_COMBINER_PERMISSION);
235                }
236                return combiner;
237            }
238
239            /** 
240             * Determines whether the access request indicated by the
241             * specified permission should be allowed or denied, based on
242             * the security policy currently in effect, and the context in
243             * this object. The request is allowed only if every ProtectionDomain
244             * in the context implies the permission. Otherwise the request is
245             * denied.
246             * 
247             * <p>
248             * This method quietly returns if the access request
249             * is permitted, or throws a suitable AccessControlException otherwise. 
250             *
251             * @param perm the requested permission.
252             * 
253             * @exception AccessControlException if the specified permission
254             * is not permitted, based on the current security policy and the
255             * context encapsulated by this object.
256             * @exception NullPointerException if the permission to check for is null.
257             */
258            public void checkPermission(Permission perm)
259                    throws AccessControlException {
260                boolean dumpDebug = false;
261
262                if (perm == null) {
263                    throw new NullPointerException("permission can't be null");
264                }
265                if (getDebug() != null) {
266                    // If "codebase" is not specified, we dump the info by default.
267                    dumpDebug = !Debug.isOn("codebase=");
268                    if (!dumpDebug) {
269                        // If "codebase" is specified, only dump if the specified code
270                        // value is in the stack.
271                        for (int i = 0; context != null && i < context.length; i++) {
272                            if (context[i].getCodeSource() != null
273                                    && context[i].getCodeSource().getLocation() != null
274                                    && Debug.isOn("codebase="
275                                            + context[i].getCodeSource()
276                                                    .getLocation().toString())) {
277                                dumpDebug = true;
278                                break;
279                            }
280                        }
281                    }
282
283                    dumpDebug &= !Debug.isOn("permission=")
284                            || Debug.isOn("permission="
285                                    + perm.getClass().getCanonicalName());
286
287                    if (dumpDebug && Debug.isOn("stack")) {
288                        Thread.currentThread().dumpStack();
289                    }
290
291                    if (dumpDebug && Debug.isOn("domain")) {
292                        if (context == null) {
293                            debug.println("domain (context is null)");
294                        } else {
295                            for (int i = 0; i < context.length; i++) {
296                                debug.println("domain " + i + " " + context[i]);
297                            }
298                        }
299                    }
300                }
301
302                /*
303                 * iterate through the ProtectionDomains in the context.
304                 * Stop at the first one that doesn't allow the
305                 * requested permission (throwing an exception).
306                 *
307                 */
308
309                /* if ctxt is null, all we had on the stack were system domains,
310                   or the first domain was a Privileged system domain. This
311                   is to make the common case for system code very fast */
312
313                if (context == null)
314                    return;
315
316                for (int i = 0; i < context.length; i++) {
317                    if (context[i] != null && !context[i].implies(perm)) {
318                        if (dumpDebug) {
319                            debug.println("access denied " + perm);
320                        }
321
322                        if (Debug.isOn("failure")) {
323                            // Want to make sure this is always displayed for failure,
324                            // but do not want to display again if already displayed
325                            // above.
326                            if (!dumpDebug) {
327                                debug.println("access denied " + perm);
328                            }
329                            Thread.currentThread().dumpStack();
330                            final ProtectionDomain pd = context[i];
331                            final Debug db = debug;
332                            AccessController
333                                    .doPrivileged(new PrivilegedAction<Void>() {
334                                        public Void run() {
335                                            db.println("domain that failed "
336                                                    + pd);
337                                            return null;
338                                        }
339                                    });
340                        }
341                        throw new AccessControlException("access denied "
342                                + perm, perm);
343                    }
344                }
345
346                // allow if all of them allowed access
347                if (dumpDebug) {
348                    debug.println("access allowed " + perm);
349                }
350
351                return;
352            }
353
354            /**
355             * Take the stack-based context (this) and combine it with the
356             * privileged or inherited context, if need be.
357             */
358            AccessControlContext optimize() {
359                // the assigned (privileged or inherited) context
360                AccessControlContext acc;
361                if (isPrivileged) {
362                    acc = privilegedContext;
363                } else {
364                    acc = AccessController.getInheritedAccessControlContext();
365                }
366
367                // this.context could be null if only system code is on the stack;
368                // in that case, ignore the stack context
369                boolean skipStack = (context == null);
370
371                // acc.context could be null if only system code was involved;
372                // in that case, ignore the assigned context
373                boolean skipAssigned = (acc == null || acc.context == null);
374
375                if (acc != null && acc.combiner != null) {
376                    // let the assigned acc's combiner do its thing
377                    return goCombiner(context, acc);
378                }
379
380                // optimization: if neither have contexts; return acc if possible
381                // rather than this, because acc might have a combiner
382                if (skipAssigned && skipStack) {
383                    return this ;
384                }
385
386                // optimization: if there is no stack context; there is no reason
387                // to compress the assigned context, it already is compressed
388                if (skipStack) {
389                    return acc;
390                }
391
392                int slen = context.length;
393
394                // optimization: if there is no assigned context and the stack length
395                // is less then or equal to two; there is no reason to compress the
396                // stack context, it already is
397                if (skipAssigned && slen <= 2) {
398                    return this ;
399                }
400
401                // optimization: if there is a single stack domain and that domain
402                // is already in the assigned context; no need to combine
403                if ((slen == 1) && (context[0] == acc.context[0])) {
404                    return acc;
405                }
406
407                int n = (skipAssigned) ? 0 : acc.context.length;
408
409                // now we combine both of them, and create a new context
410                ProtectionDomain pd[] = new ProtectionDomain[slen + n];
411
412                // first copy in the assigned context domains, no need to compress
413                if (!skipAssigned) {
414                    System.arraycopy(acc.context, 0, pd, 0, n);
415                }
416
417                // now add the stack context domains, discarding nulls and duplicates
418                outer: for (int i = 0; i < context.length; i++) {
419                    ProtectionDomain sd = context[i];
420                    if (sd != null) {
421                        for (int j = 0; j < n; j++) {
422                            if (sd == pd[j]) {
423                                continue outer;
424                            }
425                        }
426                        pd[n++] = sd;
427                    }
428                }
429
430                // if length isn't equal, we need to shorten the array
431                if (n != pd.length) {
432                    // optimization: if we didn't really combine anything
433                    if (!skipAssigned && n == acc.context.length) {
434                        return acc;
435                    } else if (skipAssigned && n == slen) {
436                        return this ;
437                    }
438                    ProtectionDomain tmp[] = new ProtectionDomain[n];
439                    System.arraycopy(pd, 0, tmp, 0, n);
440                    pd = tmp;
441                }
442
443                //	return new AccessControlContext(pd, false);
444
445                // Reuse existing ACC
446
447                this .context = pd;
448                this .combiner = null;
449                this .isPrivileged = false;
450
451                return this ;
452            }
453
454            private AccessControlContext goCombiner(ProtectionDomain[] current,
455                    AccessControlContext assigned) {
456
457                // the assigned ACC's combiner is not null --
458                // let the combiner do its thing
459
460                // XXX we could add optimizations to 'current' here ...
461
462                if (getDebug() != null) {
463                    debug.println("AccessControlContext invoking the Combiner");
464                }
465
466                // No need to clone current and assigned.context
467                // combine() will not update them
468                ProtectionDomain[] combinedPds = assigned.combiner.combine(
469                        current, assigned.context);
470
471                // return new AccessControlContext(combinedPds, assigned.combiner);
472
473                // Reuse existing ACC
474                this .context = combinedPds;
475                this .combiner = assigned.combiner;
476                this .isPrivileged = false;
477
478                return this ;
479            }
480
481            /**
482             * Checks two AccessControlContext objects for equality. 
483             * Checks that <i>obj</i> is
484             * an AccessControlContext and has the same set of ProtectionDomains
485             * as this context.
486             * <P>
487             * @param obj the object we are testing for equality with this object.
488             * @return true if <i>obj</i> is an AccessControlContext, and has the 
489             * same set of ProtectionDomains as this context, false otherwise.
490             */
491            public boolean equals(Object obj) {
492                if (obj == this )
493                    return true;
494
495                if (!(obj instanceof  AccessControlContext))
496                    return false;
497
498                AccessControlContext that = (AccessControlContext) obj;
499
500                if (context == null) {
501                    return (that.context == null);
502                }
503
504                if (that.context == null)
505                    return false;
506
507                if (!(this .containsAllPDs(that) && that.containsAllPDs(this )))
508                    return false;
509
510                if (this .combiner == null)
511                    return (that.combiner == null);
512
513                if (that.combiner == null)
514                    return false;
515
516                if (!this .combiner.equals(that.combiner))
517                    return false;
518
519                return true;
520            }
521
522            private boolean containsAllPDs(AccessControlContext that) {
523                boolean match = false;
524                //
525                // ProtectionDomains within an ACC currently cannot be null
526                // and this is enforced by the constructor and the various
527                // optimize methods. However, historically this logic made attempts
528                // to support the notion of a null PD and therefore this logic continues
529                // to support that notion.
530                ProtectionDomain this Pd;
531                for (int i = 0; i < context.length; i++) {
532                    match = false;
533                    if ((this Pd = context[i]) == null) {
534                        for (int j = 0; (j < that.context.length) && !match; j++) {
535                            match = (that.context[j] == null);
536                        }
537                    } else {
538                        Class this PdClass = this Pd.getClass();
539                        ProtectionDomain thatPd;
540                        for (int j = 0; (j < that.context.length) && !match; j++) {
541                            thatPd = that.context[j];
542
543                            // Class check required to avoid PD exposure (4285406)
544                            match = (thatPd != null
545                                    && this PdClass == thatPd.getClass() && this Pd
546                                    .equals(thatPd));
547                        }
548                    }
549                    if (!match)
550                        return false;
551                }
552                return match;
553            }
554
555            /**
556             * Returns the hash code value for this context. The hash code
557             * is computed by exclusive or-ing the hash code of all the protection
558             * domains in the context together.
559             * 
560             * @return a hash code value for this context.
561             */
562
563            public int hashCode() {
564                int hashCode = 0;
565
566                if (context == null)
567                    return hashCode;
568
569                for (int i = 0; i < context.length; i++) {
570                    if (context[i] != null)
571                        hashCode ^= context[i].hashCode();
572                }
573                return hashCode;
574            }
575        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.