Source Code Cross Referenced for SubjectDomainCombiner.java in  » 6.0-JDK-Core » security » javax » security » auth » 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 » javax.security.auth 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001        /*
002         * Copyright 1999-2007 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 javax.security.auth;
027
028        import java.security.AccessController;
029        import java.security.AccessControlContext;
030        import java.security.AllPermission;
031        import java.security.Permission;
032        import java.security.Permissions;
033        import java.security.PermissionCollection;
034        import java.security.Policy;
035        import java.security.Principal;
036        import java.security.PrivilegedAction;
037        import java.security.ProtectionDomain;
038        import java.lang.ClassLoader;
039        import java.security.Security;
040        import java.util.Set;
041        import java.util.Iterator;
042        import java.util.WeakHashMap;
043        import java.lang.ref.WeakReference;
044
045        /**
046         * A <code>SubjectDomainCombiner</code> updates ProtectionDomains
047         * with Principals from the <code>Subject</code> associated with this
048         * <code>SubjectDomainCombiner</code>.
049         *
050         * @version 1.57, 05/05/07
051         */
052        public class SubjectDomainCombiner implements 
053                java.security.DomainCombiner {
054
055            private Subject subject;
056            private WeakKeyValueMap<ProtectionDomain, ProtectionDomain> cachedPDs = new WeakKeyValueMap<ProtectionDomain, ProtectionDomain>();
057            private Set<Principal> principalSet;
058            private Principal[] principals;
059
060            private static final sun.security.util.Debug debug = sun.security.util.Debug
061                    .getInstance("combiner", "\t[SubjectDomainCombiner]");
062
063            // Note: check only at classloading time, not dynamically during combine()
064            private static final boolean useJavaxPolicy = compatPolicy();
065
066            // Relevant only when useJavaxPolicy is true
067            private static final boolean allowCaching = (useJavaxPolicy && cachePolicy());
068
069            /**
070             * Associate the provided <code>Subject</code> with this
071             * <code>SubjectDomainCombiner</code>.
072             *
073             * <p>
074             *
075             * @param subject the <code>Subject</code> to be associated with
076             *		with this <code>SubjectDomainCombiner</code>.
077             */
078            public SubjectDomainCombiner(Subject subject) {
079                this .subject = subject;
080
081                if (subject.isReadOnly()) {
082                    principalSet = subject.getPrincipals();
083                    principals = (Principal[]) principalSet
084                            .toArray(new Principal[principalSet.size()]);
085                }
086            }
087
088            /**
089             * Get the <code>Subject</code> associated with this
090             * <code>SubjectDomainCombiner</code>.
091             *
092             * <p>
093             *
094             * @return the <code>Subject</code> associated with this
095             *		<code>SubjectDomainCombiner</code>, or <code>null</code>
096             *		if no <code>Subject</code> is associated with this
097             *		<code>SubjectDomainCombiner</code>.
098             *
099             * @exception SecurityException if the caller does not have permission
100             *		to get the <code>Subject</code> associated with this
101             *		<code>SubjectDomainCombiner</code>.
102             */
103            public Subject getSubject() {
104                java.lang.SecurityManager sm = System.getSecurityManager();
105                if (sm != null) {
106                    sm.checkPermission(new AuthPermission(
107                            "getSubjectFromDomainCombiner"));
108                }
109                return subject;
110            }
111
112            /**
113             * Update the relevant ProtectionDomains with the Principals
114             * from the <code>Subject</code> associated with this
115             * <code>SubjectDomainCombiner</code>.
116             *
117             * <p> A new <code>ProtectionDomain</code> instance is created
118             * for each <code>ProtectionDomain</code> in the
119             * <i>currentDomains</i> array.  Each new <code>ProtectionDomain</code>
120             * instance is created using the <code>CodeSource</code>,
121             * <code>Permission</code>s and <code>ClassLoader</code>
122             * from the corresponding <code>ProtectionDomain</code> in
123             * <i>currentDomains</i>, as well as with the Principals from
124             * the <code>Subject</code> associated with this
125             * <code>SubjectDomainCombiner</code>.
126             * 
127             * <p> All of the newly instantiated ProtectionDomains are
128             * combined into a new array.  The ProtectionDomains from the
129             * <i>assignedDomains</i> array are appended to this new array,
130             * and the result is returned.
131             *
132             * <p> Note that optimizations such as the removal of duplicate
133             * ProtectionDomains may have occurred.
134             * In addition, caching of ProtectionDomains may be permitted.
135             *
136             * <p>
137             *
138             * @param currentDomains the ProtectionDomains associated with the
139             *		current execution Thread, up to the most recent
140             *		privileged <code>ProtectionDomain</code>.
141             *		The ProtectionDomains are are listed in order of execution,
142             *		with the most recently executing <code>ProtectionDomain</code>
143             *		residing at the beginning of the array. This parameter may
144             *		be <code>null</code> if the current execution Thread
145             *		has no associated ProtectionDomains.<p>
146             *
147             * @param assignedDomains the ProtectionDomains inherited from the
148             *		parent Thread, or the ProtectionDomains from the
149             *		privileged <i>context</i>, if a call to
150             *		AccessController.doPrivileged(..., <i>context</i>)
151             *		had occurred  This parameter may be <code>null</code>
152             *		if there were no ProtectionDomains inherited from the
153             *		parent Thread, or from the privileged <i>context</i>.
154             *
155             * @return a new array consisting of the updated ProtectionDomains,
156             *		or <code>null</code>.
157             */
158            public ProtectionDomain[] combine(
159                    ProtectionDomain[] currentDomains,
160                    ProtectionDomain[] assignedDomains) {
161                if (debug != null) {
162                    if (subject == null) {
163                        debug.println("null subject");
164                    } else {
165                        final Subject s = subject;
166                        AccessController
167                                .doPrivileged(new java.security.PrivilegedAction<Void>() {
168                                    public Void run() {
169                                        debug.println(s.toString());
170                                        return null;
171                                    }
172                                });
173                    }
174                    printInputDomains(currentDomains, assignedDomains);
175                }
176
177                if (currentDomains == null || currentDomains.length == 0) {
178                    // No need to optimize assignedDomains because it should
179                    // have been previously optimized (when it was set).
180
181                    // Note that we are returning a direct reference
182                    // to the input array - since ACC does not clone
183                    // the arrays when it calls combiner.combine,
184                    // multiple ACC instances may share the same
185                    // array instance in this case
186
187                    return assignedDomains;
188                }
189
190                // optimize currentDomains
191                //
192                // No need to optimize assignedDomains because it should
193                // have been previously optimized (when it was set).
194
195                currentDomains = optimize(currentDomains);
196                if (debug != null) {
197                    debug.println("after optimize");
198                    printInputDomains(currentDomains, assignedDomains);
199                }
200
201                if (currentDomains == null && assignedDomains == null) {
202                    return null;
203                }
204
205                // maintain backwards compatibility for people who provide
206                // their own javax.security.auth.Policy implementations
207                if (useJavaxPolicy) {
208                    return combineJavaxPolicy(currentDomains, assignedDomains);
209                }
210
211                int cLen = (currentDomains == null ? 0 : currentDomains.length);
212                int aLen = (assignedDomains == null ? 0
213                        : assignedDomains.length);
214
215                // the ProtectionDomains for the new AccessControlContext
216                // that we will return
217                ProtectionDomain[] newDomains = new ProtectionDomain[cLen
218                        + aLen];
219
220                boolean allNew = true;
221                synchronized (cachedPDs) {
222                    if (!subject.isReadOnly()
223                            && !subject.getPrincipals().equals(principalSet)) {
224
225                        // if the Subject was mutated, clear the PD cache
226                        Set<Principal> newSet = subject.getPrincipals();
227                        synchronized (newSet) {
228                            principalSet = new java.util.HashSet<Principal>(
229                                    newSet);
230                        }
231                        principals = (Principal[]) principalSet
232                                .toArray(new Principal[principalSet.size()]);
233                        cachedPDs.clear();
234
235                        if (debug != null) {
236                            debug.println("Subject mutated - clearing cache");
237                        }
238                    }
239
240                    ProtectionDomain subjectPd;
241                    for (int i = 0; i < cLen; i++) {
242                        ProtectionDomain pd = currentDomains[i];
243
244                        subjectPd = cachedPDs.getValue(pd);
245
246                        if (subjectPd == null) {
247                            subjectPd = new ProtectionDomain(
248                                    pd.getCodeSource(), pd.getPermissions(), pd
249                                            .getClassLoader(), principals);
250                            cachedPDs.putValue(pd, subjectPd);
251                        } else {
252                            allNew = false;
253                        }
254                        newDomains[i] = subjectPd;
255                    }
256                }
257
258                if (debug != null) {
259                    debug.println("updated current: ");
260                    for (int i = 0; i < cLen; i++) {
261                        debug.println("\tupdated[" + i + "] = "
262                                + printDomain(newDomains[i]));
263                    }
264                }
265
266                // now add on the assigned domains
267                if (aLen > 0) {
268                    System
269                            .arraycopy(assignedDomains, 0, newDomains, cLen,
270                                    aLen);
271
272                    // optimize the result (cached PDs might exist in assignedDomains)
273                    if (!allNew) {
274                        newDomains = optimize(newDomains);
275                    }
276                }
277
278                // if aLen == 0 || allNew, no need to further optimize newDomains
279
280                if (debug != null) {
281                    if (newDomains == null || newDomains.length == 0) {
282                        debug.println("returning null");
283                    } else {
284                        debug.println("combinedDomains: ");
285                        for (int i = 0; i < newDomains.length; i++) {
286                            debug.println("newDomain " + i + ": "
287                                    + printDomain(newDomains[i]));
288                        }
289                    }
290                }
291
292                // return the new ProtectionDomains
293                if (newDomains == null || newDomains.length == 0) {
294                    return null;
295                } else {
296                    return newDomains;
297                }
298            }
299
300            /**
301             * Use the javax.security.auth.Policy implementation
302             */
303            private ProtectionDomain[] combineJavaxPolicy(
304                    ProtectionDomain[] currentDomains,
305                    ProtectionDomain[] assignedDomains) {
306
307                if (!allowCaching) {
308                    java.security.AccessController
309                            .doPrivileged(new PrivilegedAction<Void>() {
310                                public Void run() {
311                                    // Call refresh only caching is disallowed
312                                    javax.security.auth.Policy.getPolicy()
313                                            .refresh();
314                                    return null;
315                                }
316                            });
317                }
318
319                int cLen = (currentDomains == null ? 0 : currentDomains.length);
320                int aLen = (assignedDomains == null ? 0
321                        : assignedDomains.length);
322
323                // the ProtectionDomains for the new AccessControlContext
324                // that we will return
325                ProtectionDomain[] newDomains = new ProtectionDomain[cLen
326                        + aLen];
327
328                synchronized (cachedPDs) {
329                    if (!subject.isReadOnly()
330                            && !subject.getPrincipals().equals(principalSet)) {
331
332                        // if the Subject was mutated, clear the PD cache
333                        Set<Principal> newSet = subject.getPrincipals();
334                        synchronized (newSet) {
335                            principalSet = new java.util.HashSet<Principal>(
336                                    newSet);
337                        }
338                        principals = (Principal[]) principalSet
339                                .toArray(new Principal[principalSet.size()]);
340                        cachedPDs.clear();
341
342                        if (debug != null) {
343                            debug.println("Subject mutated - clearing cache");
344                        }
345                    }
346
347                    for (int i = 0; i < cLen; i++) {
348                        ProtectionDomain pd = currentDomains[i];
349                        ProtectionDomain subjectPd = cachedPDs.getValue(pd);
350
351                        if (subjectPd == null) {
352
353                            // XXX 
354                            // we must first add the original permissions.
355                            // that way when we later add the new JAAS permissions,
356                            // any unresolved JAAS-related permissions will
357                            // automatically get resolved.
358
359                            // get the original perms
360                            Permissions perms = new Permissions();
361                            PermissionCollection coll = pd.getPermissions();
362                            java.util.Enumeration e;
363                            if (coll != null) {
364                                synchronized (coll) {
365                                    e = coll.elements();
366                                    while (e.hasMoreElements()) {
367                                        Permission newPerm = (Permission) e
368                                                .nextElement();
369                                        perms.add(newPerm);
370                                    }
371                                }
372                            }
373
374                            // get perms from the policy
375
376                            final java.security.CodeSource finalCs = pd
377                                    .getCodeSource();
378                            final Subject finalS = subject;
379                            PermissionCollection newPerms = java.security.AccessController
380                                    .doPrivileged(new PrivilegedAction<PermissionCollection>() {
381                                        public PermissionCollection run() {
382                                            return javax.security.auth.Policy
383                                                    .getPolicy()
384                                                    .getPermissions(finalS,
385                                                            finalCs);
386                                        }
387                                    });
388
389                            // add the newly granted perms,
390                            // avoiding duplicates
391                            synchronized (newPerms) {
392                                e = newPerms.elements();
393                                while (e.hasMoreElements()) {
394                                    Permission newPerm = (Permission) e
395                                            .nextElement();
396                                    if (!perms.implies(newPerm)) {
397                                        perms.add(newPerm);
398                                        if (debug != null)
399                                            debug.println("Adding perm "
400                                                    + newPerm + "\n");
401                                    }
402                                }
403                            }
404                            subjectPd = new ProtectionDomain(finalCs, perms, pd
405                                    .getClassLoader(), principals);
406
407                            if (allowCaching)
408                                cachedPDs.putValue(pd, subjectPd);
409                        }
410                        newDomains[i] = subjectPd;
411                    }
412                }
413
414                if (debug != null) {
415                    debug.println("updated current: ");
416                    for (int i = 0; i < cLen; i++) {
417                        debug
418                                .println("\tupdated[" + i + "] = "
419                                        + newDomains[i]);
420                    }
421                }
422
423                // now add on the assigned domains
424                if (aLen > 0) {
425                    System
426                            .arraycopy(assignedDomains, 0, newDomains, cLen,
427                                    aLen);
428                }
429
430                if (debug != null) {
431                    if (newDomains == null || newDomains.length == 0) {
432                        debug.println("returning null");
433                    } else {
434                        debug.println("combinedDomains: ");
435                        for (int i = 0; i < newDomains.length; i++) {
436                            debug.println("newDomain " + i + ": "
437                                    + newDomains[i].toString());
438                        }
439                    }
440                }
441
442                // return the new ProtectionDomains
443                if (newDomains == null || newDomains.length == 0) {
444                    return null;
445                } else {
446                    return newDomains;
447                }
448            }
449
450            private static ProtectionDomain[] optimize(
451                    ProtectionDomain[] domains) {
452                if (domains == null || domains.length == 0)
453                    return null;
454
455                ProtectionDomain[] optimized = new ProtectionDomain[domains.length];
456                ProtectionDomain pd;
457                int num = 0;
458                for (int i = 0; i < domains.length; i++) {
459
460                    // skip domains with AllPermission 
461                    // XXX
462                    //
463                    //	if (domains[i].implies(ALL_PERMISSION))
464                    //	continue;
465
466                    // skip System Domains
467                    if ((pd = domains[i]) != null) {
468
469                        // remove duplicates
470                        boolean found = false;
471                        for (int j = 0; j < num && !found; j++) {
472                            found = (optimized[j] == pd);
473                        }
474                        if (!found) {
475                            optimized[num++] = pd;
476                        }
477                    }
478                }
479
480                // resize the array if necessary
481                if (num > 0 && num < domains.length) {
482                    ProtectionDomain[] downSize = new ProtectionDomain[num];
483                    System
484                            .arraycopy(optimized, 0, downSize, 0,
485                                    downSize.length);
486                    optimized = downSize;
487                }
488
489                return ((num == 0 || optimized.length == 0) ? null : optimized);
490            }
491
492            private static boolean cachePolicy() {
493                String s = AccessController
494                        .doPrivileged(new PrivilegedAction<String>() {
495                            public String run() {
496                                return java.security.Security
497                                        .getProperty("cache.auth.policy");
498                            }
499                        });
500                if (s != null) {
501                    return Boolean.parseBoolean(s);
502                }
503
504                // cache by default
505                return true;
506            }
507
508            // maintain backwards compatibility for people who provide
509            // their own javax.security.auth.Policy implementations
510            private static boolean compatPolicy() {
511                javax.security.auth.Policy javaxPolicy = AccessController
512                        .doPrivileged(new PrivilegedAction<javax.security.auth.Policy>() {
513                            public javax.security.auth.Policy run() {
514                                return javax.security.auth.Policy.getPolicy();
515                            }
516                        });
517
518                if (!(javaxPolicy instanceof  com.sun.security.auth.PolicyFile)) {
519                    if (debug != null) {
520                        debug.println("Providing backwards compatibility for "
521                                + "javax.security.auth.policy implementation: "
522                                + javaxPolicy.toString());
523                    }
524
525                    return true;
526                } else {
527                    return false;
528                }
529            }
530
531            private static void printInputDomains(
532                    ProtectionDomain[] currentDomains,
533                    ProtectionDomain[] assignedDomains) {
534                if (currentDomains == null || currentDomains.length == 0) {
535                    debug.println("currentDomains null or 0 length");
536                } else {
537                    for (int i = 0; currentDomains != null
538                            && i < currentDomains.length; i++) {
539                        if (currentDomains[i] == null) {
540                            debug.println("currentDomain " + i
541                                    + ": SystemDomain");
542                        } else {
543                            debug.println("currentDomain " + i + ": "
544                                    + printDomain(currentDomains[i]));
545                        }
546                    }
547                }
548
549                if (assignedDomains == null || assignedDomains.length == 0) {
550                    debug.println("assignedDomains null or 0 length");
551                } else {
552                    debug.println("assignedDomains = ");
553                    for (int i = 0; assignedDomains != null
554                            && i < assignedDomains.length; i++) {
555                        if (assignedDomains[i] == null) {
556                            debug.println("assignedDomain " + i
557                                    + ": SystemDomain");
558                        } else {
559                            debug.println("assignedDomain " + i + ": "
560                                    + printDomain(assignedDomains[i]));
561                        }
562                    }
563                }
564            }
565
566            private static String printDomain(final ProtectionDomain pd) {
567                if (pd == null) {
568                    return "null";
569                }
570                return AccessController
571                        .doPrivileged(new PrivilegedAction<String>() {
572                            public String run() {
573                                return pd.toString();
574                            }
575                        });
576            }
577
578            /**
579             * A HashMap that has weak keys and values.
580             *
581             * Key objects in this map are the "current" ProtectionDomain instances
582             * received via the combine method.  Each "current" PD is mapped to a
583             * new PD instance that holds both the contents of the "current" PD,
584             * as well as the principals from the Subject associated with this combiner.
585             *
586             * The newly created "principal-based" PD values must be stored as
587             * WeakReferences since they contain strong references to the
588             * corresponding key object (the "current" non-principal-based PD),
589             * which will prevent the key from being GC'd.  Specifically,
590             * a "principal-based" PD contains strong references to the CodeSource,
591             * signer certs, PermissionCollection and ClassLoader objects
592             * in the "current PD".
593             */
594            private static class WeakKeyValueMap<K, V> extends
595                    WeakHashMap<K, WeakReference<V>> {
596
597                public V getValue(K key) {
598                    WeakReference<V> wr = super .get(key);
599                    if (wr != null) {
600                        return wr.get();
601                    }
602                    return null;
603                }
604
605                public V putValue(K key, V value) {
606                    WeakReference<V> wr = super .put(key, new WeakReference<V>(
607                            value));
608                    if (wr != null) {
609                        return wr.get();
610                    }
611                    return null;
612                }
613            }
614        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.