jdk/src/share/classes/com/sun/security/auth/SubjectCodeSource.java
changeset 19629 2b74fcdca60e
parent 19628 6d484513c9fc
parent 19516 589f4fdc584e
child 19639 aa4207b72f72
equal deleted inserted replaced
19628:6d484513c9fc 19629:2b74fcdca60e
     1 /*
       
     2  * Copyright (c) 1999, 2013, Oracle and/or its affiliates. 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.  Oracle designates this
       
     8  * particular file as subject to the "Classpath" exception as provided
       
     9  * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
       
    22  * or visit www.oracle.com if you need additional information or have any
       
    23  * questions.
       
    24  */
       
    25 
       
    26 package com.sun.security.auth;
       
    27 
       
    28 import java.net.URL;
       
    29 import java.util.*;
       
    30 import java.security.CodeSource;
       
    31 import java.security.Principal;
       
    32 import java.security.cert.Certificate;
       
    33 import java.lang.reflect.Constructor;
       
    34 
       
    35 import javax.security.auth.Subject;
       
    36 import sun.security.provider.PolicyParser.PrincipalEntry;
       
    37 
       
    38 /**
       
    39  * <p> This <code>SubjectCodeSource</code> class contains
       
    40  * a <code>URL</code>, signer certificates, and either a <code>Subject</code>
       
    41  * (that represents the <code>Subject</code> in the current
       
    42  * <code>AccessControlContext</code>),
       
    43  * or a linked list of Principals/PrincipalComparators
       
    44  * (that represent a "subject" in a <code>Policy</code>).
       
    45  *
       
    46  */
       
    47 class SubjectCodeSource extends CodeSource implements java.io.Serializable {
       
    48 
       
    49     private static final long serialVersionUID = 6039418085604715275L;
       
    50 
       
    51     private static final java.util.ResourceBundle rb =
       
    52         java.security.AccessController.doPrivileged
       
    53         (new java.security.PrivilegedAction<java.util.ResourceBundle>() {
       
    54             public java.util.ResourceBundle run() {
       
    55                 return (java.util.ResourceBundle.getBundle
       
    56                         ("sun.security.util.AuthResources"));
       
    57             }
       
    58         });
       
    59 
       
    60     private Subject subject;
       
    61     private LinkedList<PrincipalEntry> principals;
       
    62     private static final Class[] PARAMS = { String.class };
       
    63     private static final sun.security.util.Debug debug =
       
    64         sun.security.util.Debug.getInstance("auth", "\t[Auth Access]");
       
    65     private ClassLoader sysClassLoader;
       
    66 
       
    67     /**
       
    68      * Creates a new <code>SubjectCodeSource</code>
       
    69      * with the given <code>Subject</code>, principals, <code>URL</code>,
       
    70      * and signers (Certificates).  The <code>Subject</code>
       
    71      * represents the <code>Subject</code> associated with the current
       
    72      * <code>AccessControlContext</code>.
       
    73      * The Principals are given as a <code>LinkedList</code>
       
    74      * of <code>PolicyParser.PrincipalEntry</code> objects.
       
    75      * Typically either a <code>Subject</code> will be provided,
       
    76      * or a list of <code>principals</code> will be provided
       
    77      * (not both).
       
    78      *
       
    79      * <p>
       
    80      *
       
    81      * @param subject the <code>Subject</code> associated with this
       
    82      *                  <code>SubjectCodeSource</code> <p>
       
    83      *
       
    84      * @param url the <code>URL</code> associated with this
       
    85      *                  <code>SubjectCodeSource</code> <p>
       
    86      *
       
    87      * @param certs the signers associated with this
       
    88      *                  <code>SubjectCodeSource</code> <p>
       
    89      */
       
    90     SubjectCodeSource(Subject subject,
       
    91         LinkedList<PrincipalEntry> principals,
       
    92         URL url, Certificate[] certs) {
       
    93 
       
    94         super(url, certs);
       
    95         this.subject = subject;
       
    96         this.principals = (principals == null ?
       
    97                 new LinkedList<PrincipalEntry>() :
       
    98                 new LinkedList<PrincipalEntry>(principals));
       
    99         sysClassLoader = java.security.AccessController.doPrivileged
       
   100         (new java.security.PrivilegedAction<ClassLoader>() {
       
   101             public ClassLoader run() {
       
   102                     return ClassLoader.getSystemClassLoader();
       
   103             }
       
   104         });
       
   105     }
       
   106 
       
   107     /**
       
   108      * Get the Principals associated with this <code>SubjectCodeSource</code>.
       
   109      * The Principals are retrieved as a <code>LinkedList</code>
       
   110      * of <code>PolicyParser.PrincipalEntry</code> objects.
       
   111      *
       
   112      * <p>
       
   113      *
       
   114      * @return the Principals associated with this
       
   115      *          <code>SubjectCodeSource</code> as a <code>LinkedList</code>
       
   116      *          of <code>PolicyParser.PrincipalEntry</code> objects.
       
   117      */
       
   118     LinkedList<PrincipalEntry> getPrincipals() {
       
   119         return principals;
       
   120     }
       
   121 
       
   122     /**
       
   123      * Get the <code>Subject</code> associated with this
       
   124      * <code>SubjectCodeSource</code>.  The <code>Subject</code>
       
   125      * represents the <code>Subject</code> associated with the
       
   126      * current <code>AccessControlContext</code>.
       
   127      *
       
   128      * <p>
       
   129      *
       
   130      * @return the <code>Subject</code> associated with this
       
   131      *          <code>SubjectCodeSource</code>.
       
   132      */
       
   133     Subject getSubject() {
       
   134         return subject;
       
   135     }
       
   136 
       
   137     /**
       
   138      * Returns true if this <code>SubjectCodeSource</code> object "implies"
       
   139      * the specified <code>CodeSource</code>.
       
   140      * More specifically, this method makes the following checks.
       
   141      * If any fail, it returns false.  If they all succeed, it returns true.
       
   142      *
       
   143      * <p>
       
   144      * <ol>
       
   145      * <li> The provided codesource must not be <code>null</code>.
       
   146      * <li> codesource must be an instance of <code>SubjectCodeSource</code>.
       
   147      * <li> super.implies(codesource) must return true.
       
   148      * <li> for each principal in this codesource's principal list:
       
   149      * <ol>
       
   150      * <li>     if the principal is an instanceof
       
   151      *          <code>PrincipalComparator</code>, then the principal must
       
   152      *          imply the provided codesource's <code>Subject</code>.
       
   153      * <li>     if the principal is not an instanceof
       
   154      *          <code>PrincipalComparator</code>, then the provided
       
   155      *          codesource's <code>Subject</code> must have an
       
   156      *          associated <code>Principal</code>, <i>P</i>, where
       
   157      *          P.getClass().getName equals principal.principalClass,
       
   158      *          and P.getName() equals principal.principalName.
       
   159      * </ol>
       
   160      * </ol>
       
   161      *
       
   162      * <p>
       
   163      *
       
   164      * @param codesource the <code>CodeSource</code> to compare against.
       
   165      *
       
   166      * @return true if this <code>SubjectCodeSource</code> implies the
       
   167      *          the specified <code>CodeSource</code>.
       
   168      */
       
   169     public boolean implies(CodeSource codesource) {
       
   170 
       
   171         LinkedList<PrincipalEntry> subjectList = null;
       
   172 
       
   173         if (codesource == null ||
       
   174             !(codesource instanceof SubjectCodeSource) ||
       
   175             !(super.implies(codesource))) {
       
   176 
       
   177             if (debug != null)
       
   178                 debug.println("\tSubjectCodeSource.implies: FAILURE 1");
       
   179             return false;
       
   180         }
       
   181 
       
   182         SubjectCodeSource that = (SubjectCodeSource)codesource;
       
   183 
       
   184         // if the principal list in the policy "implies"
       
   185         // the Subject associated with the current AccessControlContext,
       
   186         // then return true
       
   187 
       
   188         if (this.principals == null) {
       
   189             if (debug != null)
       
   190                 debug.println("\tSubjectCodeSource.implies: PASS 1");
       
   191             return true;
       
   192         }
       
   193 
       
   194         if (that.getSubject() == null ||
       
   195             that.getSubject().getPrincipals().size() == 0) {
       
   196             if (debug != null)
       
   197                 debug.println("\tSubjectCodeSource.implies: FAILURE 2");
       
   198             return false;
       
   199         }
       
   200 
       
   201         ListIterator<PrincipalEntry> li = this.principals.listIterator(0);
       
   202         while (li.hasNext()) {
       
   203             PrincipalEntry pppe = li.next();
       
   204             try {
       
   205 
       
   206                 // handle PrincipalComparators
       
   207 
       
   208                 Class<?> principalComparator = Class.forName(
       
   209                         pppe.getPrincipalClass(), true, sysClassLoader);
       
   210                 Constructor<?> c = principalComparator.getConstructor(PARAMS);
       
   211                 PrincipalComparator pc =
       
   212                         (PrincipalComparator)c.newInstance
       
   213                         (new Object[] { pppe.getPrincipalName() });
       
   214 
       
   215                 if (!pc.implies(that.getSubject())) {
       
   216                     if (debug != null)
       
   217                         debug.println("\tSubjectCodeSource.implies: FAILURE 3");
       
   218                     return false;
       
   219                 } else {
       
   220                     if (debug != null)
       
   221                         debug.println("\tSubjectCodeSource.implies: PASS 2");
       
   222                     return true;
       
   223                 }
       
   224             } catch (Exception e) {
       
   225 
       
   226                 // no PrincipalComparator, simply compare Principals
       
   227 
       
   228                 if (subjectList == null) {
       
   229 
       
   230                     if (that.getSubject() == null) {
       
   231                         if (debug != null)
       
   232                             debug.println("\tSubjectCodeSource.implies: " +
       
   233                                         "FAILURE 4");
       
   234                         return false;
       
   235                     }
       
   236                     Iterator<Principal> i =
       
   237                                 that.getSubject().getPrincipals().iterator();
       
   238 
       
   239                     subjectList = new LinkedList<PrincipalEntry>();
       
   240                     while (i.hasNext()) {
       
   241                         Principal p = i.next();
       
   242                         PrincipalEntry spppe = new PrincipalEntry
       
   243                                 (p.getClass().getName(), p.getName());
       
   244                         subjectList.add(spppe);
       
   245                     }
       
   246                 }
       
   247 
       
   248                 if (!subjectListImpliesPrincipalEntry(subjectList, pppe)) {
       
   249                     if (debug != null)
       
   250                         debug.println("\tSubjectCodeSource.implies: FAILURE 5");
       
   251                     return false;
       
   252                 }
       
   253             }
       
   254         }
       
   255 
       
   256         if (debug != null)
       
   257             debug.println("\tSubjectCodeSource.implies: PASS 3");
       
   258         return true;
       
   259     }
       
   260 
       
   261     /**
       
   262      * This method returns, true, if the provided <i>subjectList</i>
       
   263      * "contains" the <code>Principal</code> specified
       
   264      * in the provided <i>pppe</i> argument.
       
   265      *
       
   266      * Note that the provided <i>pppe</i> argument may have
       
   267      * wildcards (*) for the <code>Principal</code> class and name,
       
   268      * which need to be considered.
       
   269      *
       
   270      * <p>
       
   271      *
       
   272      * @param subjectList a list of PolicyParser.PrincipalEntry objects
       
   273      *          that correspond to all the Principals in the Subject currently
       
   274      *          on this thread's AccessControlContext. <p>
       
   275      *
       
   276      * @param pppe the Principals specified in a grant entry.
       
   277      *
       
   278      * @return true if the provided <i>subjectList</i> "contains"
       
   279      *          the <code>Principal</code> specified in the provided
       
   280      *          <i>pppe</i> argument.
       
   281      */
       
   282     private boolean subjectListImpliesPrincipalEntry(
       
   283                 LinkedList<PrincipalEntry> subjectList, PrincipalEntry pppe) {
       
   284 
       
   285         ListIterator<PrincipalEntry> li = subjectList.listIterator(0);
       
   286         while (li.hasNext()) {
       
   287             PrincipalEntry listPppe = li.next();
       
   288 
       
   289             if (pppe.getPrincipalClass().equals
       
   290                         (PrincipalEntry.WILDCARD_CLASS) ||
       
   291                 pppe.getPrincipalClass().equals(listPppe.getPrincipalClass()))
       
   292             {
       
   293                 if (pppe.getPrincipalName().equals
       
   294                         (PrincipalEntry.WILDCARD_NAME) ||
       
   295                     pppe.getPrincipalName().equals(listPppe.getPrincipalName()))
       
   296                     return true;
       
   297             }
       
   298         }
       
   299         return false;
       
   300     }
       
   301 
       
   302     /**
       
   303      * Tests for equality between the specified object and this
       
   304      * object. Two <code>SubjectCodeSource</code> objects are considered equal
       
   305      * if their locations are of identical value, if the two sets of
       
   306      * Certificates are of identical values, and if the
       
   307      * Subjects are equal, and if the PolicyParser.PrincipalEntry values
       
   308      * are of identical values.  It is not required that
       
   309      * the Certificates or PolicyParser.PrincipalEntry values
       
   310      * be in the same order.
       
   311      *
       
   312      * <p>
       
   313      *
       
   314      * @param obj the object to test for equality with this object.
       
   315      *
       
   316      * @return true if the objects are considered equal, false otherwise.
       
   317      */
       
   318     public boolean equals(Object obj) {
       
   319 
       
   320         if (obj == this)
       
   321             return true;
       
   322 
       
   323         if (super.equals(obj) == false)
       
   324             return false;
       
   325 
       
   326         if (!(obj instanceof SubjectCodeSource))
       
   327             return false;
       
   328 
       
   329         SubjectCodeSource that = (SubjectCodeSource)obj;
       
   330 
       
   331         // the principal lists must match
       
   332         try {
       
   333             if (this.getSubject() != that.getSubject())
       
   334                 return false;
       
   335         } catch (SecurityException se) {
       
   336             return false;
       
   337         }
       
   338 
       
   339         if ((this.principals == null && that.principals != null) ||
       
   340             (this.principals != null && that.principals == null))
       
   341             return false;
       
   342 
       
   343         if (this.principals != null && that.principals != null) {
       
   344             if (!this.principals.containsAll(that.principals) ||
       
   345                 !that.principals.containsAll(this.principals))
       
   346 
       
   347                 return false;
       
   348         }
       
   349 
       
   350         return true;
       
   351     }
       
   352 
       
   353     /**
       
   354      * Return a hashcode for this <code>SubjectCodeSource</code>.
       
   355      *
       
   356      * <p>
       
   357      *
       
   358      * @return a hashcode for this <code>SubjectCodeSource</code>.
       
   359      */
       
   360     public int hashCode() {
       
   361         return super.hashCode();
       
   362     }
       
   363 
       
   364     /**
       
   365      * Return a String representation of this <code>SubjectCodeSource</code>.
       
   366      *
       
   367      * <p>
       
   368      *
       
   369      * @return a String representation of this <code>SubjectCodeSource</code>.
       
   370      */
       
   371     public String toString() {
       
   372         String returnMe = super.toString();
       
   373         if (getSubject() != null) {
       
   374             if (debug != null) {
       
   375                 final Subject finalSubject = getSubject();
       
   376                 returnMe = returnMe + "\n" +
       
   377                         java.security.AccessController.doPrivileged
       
   378                                 (new java.security.PrivilegedAction<String>() {
       
   379                                 public String run() {
       
   380                                     return finalSubject.toString();
       
   381                                 }
       
   382                         });
       
   383             } else {
       
   384                 returnMe = returnMe + "\n" + getSubject().toString();
       
   385             }
       
   386         }
       
   387         if (principals != null) {
       
   388             ListIterator<PrincipalEntry> li = principals.listIterator();
       
   389             while (li.hasNext()) {
       
   390                 PrincipalEntry pppe = li.next();
       
   391                 returnMe = returnMe + rb.getString("NEWLINE") +
       
   392                         pppe.getPrincipalClass() + " " +
       
   393                         pppe.getPrincipalName();
       
   394             }
       
   395         }
       
   396         return returnMe;
       
   397     }
       
   398 }