Home » openjdk-7 » javax.security » auth » [javadoc | source]

    1   /*
    2    * Copyright (c) 1999, 2011, 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 javax.security.auth;
   27   
   28   import java.util;
   29   import java.text.MessageFormat;
   30   import java.security.Permission;
   31   import java.security.PermissionCollection;
   32   import java.security.Principal;
   33   import sun.security.util.ResourcesMgr;
   34   
   35   /**
   36    * This class is used to protect access to private Credentials
   37    * belonging to a particular <code>Subject</code>.  The <code>Subject</code>
   38    * is represented by a Set of Principals.
   39    *
   40    * <p> The target name of this <code>Permission</code> specifies
   41    * a Credential class name, and a Set of Principals.
   42    * The only valid value for this Permission's actions is, "read".
   43    * The target name must abide by the following syntax:
   44    *
   45    * <pre>
   46    *      CredentialClass {PrincipalClass "PrincipalName"}*
   47    * </pre>
   48    *
   49    * For example, the following permission grants access to the
   50    * com.sun.PrivateCredential owned by Subjects which have
   51    * a com.sun.Principal with the name, "duke".  Note that although
   52    * this example, as well as all the examples below, do not contain
   53    * Codebase, SignedBy, or Principal information in the grant statement
   54    * (for simplicity reasons), actual policy configurations should
   55    * specify that information when appropriate.
   56    *
   57    * <pre>
   58    *
   59    *    grant {
   60    *      permission javax.security.auth.PrivateCredentialPermission
   61    *              "com.sun.PrivateCredential com.sun.Principal \"duke\"",
   62    *              "read";
   63    *    };
   64    * </pre>
   65    *
   66    * If CredentialClass is "*", then access is granted to
   67    * all private Credentials belonging to the specified
   68    * <code>Subject</code>.
   69    * If "PrincipalName" is "*", then access is granted to the
   70    * specified Credential owned by any <code>Subject</code> that has the
   71    * specified <code>Principal</code> (the actual PrincipalName doesn't matter).
   72    * For example, the following grants access to the
   73    * a.b.Credential owned by any <code>Subject</code> that has
   74    * an a.b.Principal.
   75    *
   76    * <pre>
   77    *    grant {
   78    *      permission javax.security.auth.PrivateCredentialPermission
   79    *              "a.b.Credential a.b.Principal "*"",
   80    *              "read";
   81    *    };
   82    * </pre>
   83    *
   84    * If both the PrincipalClass and "PrincipalName" are "*",
   85    * then access is granted to the specified Credential owned by
   86    * any <code>Subject</code>.
   87    *
   88    * <p> In addition, the PrincipalClass/PrincipalName pairing may be repeated:
   89    *
   90    * <pre>
   91    *    grant {
   92    *      permission javax.security.auth.PrivateCredentialPermission
   93    *              "a.b.Credential a.b.Principal "duke" c.d.Principal "dukette"",
   94    *              "read";
   95    *    };
   96    * </pre>
   97    *
   98    * The above grants access to the private Credential, "a.b.Credential",
   99    * belonging to a <code>Subject</code> with at least two associated Principals:
  100    * "a.b.Principal" with the name, "duke", and "c.d.Principal", with the name,
  101    * "dukette".
  102    *
  103    */
  104   public final class PrivateCredentialPermission extends Permission {
  105   
  106       private static final long serialVersionUID = 5284372143517237068L;
  107   
  108       private static final CredOwner[] EMPTY_PRINCIPALS = new CredOwner[0];
  109   
  110       /**
  111        * @serial
  112        */
  113       private String credentialClass;
  114   
  115       /**
  116        * @serial The Principals associated with this permission.
  117        *          The set contains elements of type,
  118        *          <code>PrivateCredentialPermission.CredOwner</code>.
  119        */
  120       private Set principals;  // ignored - kept around for compatibility
  121       private transient CredOwner[] credOwners;
  122   
  123       /**
  124        * @serial
  125        */
  126       private boolean testing = false;
  127   
  128       /**
  129        * Create a new <code>PrivateCredentialPermission</code>
  130        * with the specified <code>credentialClass</code> and Principals.
  131        */
  132       PrivateCredentialPermission(String credentialClass,
  133                           Set<Principal> principals) {
  134   
  135           super(credentialClass);
  136           this.credentialClass = credentialClass;
  137   
  138           synchronized(principals) {
  139               if (principals.size() == 0) {
  140                   this.credOwners = EMPTY_PRINCIPALS;
  141               } else {
  142                   this.credOwners = new CredOwner[principals.size()];
  143                   int index = 0;
  144                   Iterator<Principal> i = principals.iterator();
  145                   while (i.hasNext()) {
  146                       Principal p = i.next();
  147                       this.credOwners[index++] = new CredOwner
  148                                                   (p.getClass().getName(),
  149                                                   p.getName());
  150                   }
  151               }
  152           }
  153       }
  154   
  155       /**
  156        * Creates a new <code>PrivateCredentialPermission</code>
  157        * with the specified <code>name</code>.  The <code>name</code>
  158        * specifies both a Credential class and a <code>Principal</code> Set.
  159        *
  160        * <p>
  161        *
  162        * @param name the name specifying the Credential class and
  163        *          <code>Principal</code> Set. <p>
  164        *
  165        * @param actions the actions specifying that the Credential can be read.
  166        *
  167        * @throws IllegalArgumentException if <code>name</code> does not conform
  168        *          to the correct syntax or if <code>actions</code> is not "read".
  169        */
  170       public PrivateCredentialPermission(String name, String actions) {
  171           super(name);
  172   
  173           if (!"read".equalsIgnoreCase(actions))
  174               throw new IllegalArgumentException
  175                   (ResourcesMgr.getString("actions.can.only.be.read."));
  176           init(name);
  177       }
  178   
  179       /**
  180        * Returns the Class name of the Credential associated with this
  181        * <code>PrivateCredentialPermission</code>.
  182        *
  183        * <p>
  184        *
  185        * @return the Class name of the Credential associated with this
  186        *          <code>PrivateCredentialPermission</code>.
  187        */
  188       public String getCredentialClass() {
  189           return credentialClass;
  190       }
  191   
  192       /**
  193        * Returns the <code>Principal</code> classes and names
  194        * associated with this <code>PrivateCredentialPermission</code>.
  195        * The information is returned as a two-dimensional array (array[x][y]).
  196        * The 'x' value corresponds to the number of <code>Principal</code>
  197        * class and name pairs.  When (y==0), it corresponds to
  198        * the <code>Principal</code> class value, and when (y==1),
  199        * it corresponds to the <code>Principal</code> name value.
  200        * For example, array[0][0] corresponds to the class name of
  201        * the first <code>Principal</code> in the array.  array[0][1]
  202        * corresponds to the <code>Principal</code> name of the
  203        * first <code>Principal</code> in the array.
  204        *
  205        * <p>
  206        *
  207        * @return the <code>Principal</code> class and names associated
  208        *          with this <code>PrivateCredentialPermission</code>.
  209        */
  210       public String[][] getPrincipals() {
  211   
  212           if (credOwners == null || credOwners.length == 0) {
  213               return new String[0][0];
  214           }
  215   
  216           String[][] pArray = new String[credOwners.length][2];
  217           for (int i = 0; i < credOwners.length; i++) {
  218               pArray[i][0] = credOwners[i].principalClass;
  219               pArray[i][1] = credOwners[i].principalName;
  220           }
  221           return pArray;
  222       }
  223   
  224       /**
  225        * Checks if this <code>PrivateCredentialPermission</code> implies
  226        * the specified <code>Permission</code>.
  227        *
  228        * <p>
  229        *
  230        * This method returns true if:
  231        * <p><ul>
  232        * <li> <i>p</i> is an instanceof PrivateCredentialPermission and <p>
  233        * <li> the target name for <i>p</i> is implied by this object's
  234        *          target name.  For example:
  235        * <pre>
  236        *  [* P1 "duke"] implies [a.b.Credential P1 "duke"].
  237        *  [C1 P1 "duke"] implies [C1 P1 "duke" P2 "dukette"].
  238        *  [C1 P2 "dukette"] implies [C1 P1 "duke" P2 "dukette"].
  239        * </pre>
  240        * </ul>
  241        *
  242        * <p>
  243        *
  244        * @param p the <code>Permission</code> to check against.
  245        *
  246        * @return true if this <code>PrivateCredentialPermission</code> implies
  247        * the specified <code>Permission</code>, false if not.
  248        */
  249       public boolean implies(Permission p) {
  250   
  251           if (p == null || !(p instanceof PrivateCredentialPermission))
  252               return false;
  253   
  254           PrivateCredentialPermission that = (PrivateCredentialPermission)p;
  255   
  256           if (!impliesCredentialClass(credentialClass, that.credentialClass))
  257               return false;
  258   
  259           return impliesPrincipalSet(credOwners, that.credOwners);
  260       }
  261   
  262       /**
  263        * Checks two <code>PrivateCredentialPermission</code> objects for
  264        * equality.  Checks that <i>obj</i> is a
  265        * <code>PrivateCredentialPermission</code>,
  266        * and has the same credential class as this object,
  267        * as well as the same Principals as this object.
  268        * The order of the Principals in the respective Permission's
  269        * target names is not relevant.
  270        *
  271        * <p>
  272        *
  273        * @param obj the object we are testing for equality with this object.
  274        *
  275        * @return true if obj is a <code>PrivateCredentialPermission</code>,
  276        *          has the same credential class as this object,
  277        *          and has the same Principals as this object.
  278        */
  279       public boolean equals(Object obj) {
  280           if (obj == this)
  281               return true;
  282   
  283           if (! (obj instanceof PrivateCredentialPermission))
  284               return false;
  285   
  286           PrivateCredentialPermission that = (PrivateCredentialPermission)obj;
  287   
  288           return (this.implies(that) && that.implies(this));
  289       }
  290   
  291       /**
  292        * Returns the hash code value for this object.
  293        *
  294        * @return a hash code value for this object.
  295        */
  296       public int hashCode() {
  297           return this.credentialClass.hashCode();
  298       }
  299   
  300       /**
  301        * Returns the "canonical string representation" of the actions.
  302        * This method always returns the String, "read".
  303        *
  304        * <p>
  305        *
  306        * @return the actions (always returns "read").
  307        */
  308       public String getActions() {
  309           return "read";
  310       }
  311   
  312       /**
  313        * Return a homogeneous collection of PrivateCredentialPermissions
  314        * in a <code>PermissionCollection</code>.
  315        * No such <code>PermissionCollection</code> is defined,
  316        * so this method always returns <code>null</code>.
  317        *
  318        * <p>
  319        *
  320        * @return null in all cases.
  321        */
  322       public PermissionCollection newPermissionCollection() {
  323           return null;
  324       }
  325   
  326       private void init(String name) {
  327   
  328           if (name == null || name.trim().length() == 0) {
  329               throw new IllegalArgumentException("invalid empty name");
  330           }
  331   
  332           ArrayList<CredOwner> pList = new ArrayList<>();
  333           StringTokenizer tokenizer = new StringTokenizer(name, " ", true);
  334           String principalClass = null;
  335           String principalName = null;
  336   
  337           if (testing)
  338               System.out.println("whole name = " + name);
  339   
  340           // get the Credential Class
  341           credentialClass = tokenizer.nextToken();
  342           if (testing)
  343               System.out.println("Credential Class = " + credentialClass);
  344   
  345           if (tokenizer.hasMoreTokens() == false) {
  346               MessageFormat form = new MessageFormat(ResourcesMgr.getString
  347                   ("permission.name.name.syntax.invalid."));
  348               Object[] source = {name};
  349               throw new IllegalArgumentException
  350                   (form.format(source) + ResourcesMgr.getString
  351                           ("Credential.Class.not.followed.by.a.Principal.Class.and.Name"));
  352           }
  353   
  354           while (tokenizer.hasMoreTokens()) {
  355   
  356               // skip delimiter
  357               tokenizer.nextToken();
  358   
  359               // get the Principal Class
  360               principalClass = tokenizer.nextToken();
  361               if (testing)
  362                   System.out.println("    Principal Class = " + principalClass);
  363   
  364               if (tokenizer.hasMoreTokens() == false) {
  365                   MessageFormat form = new MessageFormat(ResourcesMgr.getString
  366                           ("permission.name.name.syntax.invalid."));
  367                   Object[] source = {name};
  368                   throw new IllegalArgumentException
  369                           (form.format(source) + ResourcesMgr.getString
  370                           ("Principal.Class.not.followed.by.a.Principal.Name"));
  371               }
  372   
  373               // skip delimiter
  374               tokenizer.nextToken();
  375   
  376               // get the Principal Name
  377               principalName = tokenizer.nextToken();
  378   
  379               if (!principalName.startsWith("\"")) {
  380                   MessageFormat form = new MessageFormat(ResourcesMgr.getString
  381                           ("permission.name.name.syntax.invalid."));
  382                   Object[] source = {name};
  383                   throw new IllegalArgumentException
  384                           (form.format(source) + ResourcesMgr.getString
  385                           ("Principal.Name.must.be.surrounded.by.quotes"));
  386               }
  387   
  388               if (!principalName.endsWith("\"")) {
  389   
  390                   // we have a name with spaces in it --
  391                   // keep parsing until we find the end quote,
  392                   // and keep the spaces in the name
  393   
  394                   while (tokenizer.hasMoreTokens()) {
  395                       principalName = principalName + tokenizer.nextToken();
  396                       if (principalName.endsWith("\""))
  397                           break;
  398                   }
  399   
  400                   if (!principalName.endsWith("\"")) {
  401                       MessageFormat form = new MessageFormat
  402                           (ResourcesMgr.getString
  403                           ("permission.name.name.syntax.invalid."));
  404                       Object[] source = {name};
  405                       throw new IllegalArgumentException
  406                           (form.format(source) + ResourcesMgr.getString
  407                                   ("Principal.Name.missing.end.quote"));
  408                   }
  409               }
  410   
  411               if (testing)
  412                   System.out.println("\tprincipalName = '" + principalName + "'");
  413   
  414               principalName = principalName.substring
  415                                           (1, principalName.length() - 1);
  416   
  417               if (principalClass.equals("*") &&
  418                   !principalName.equals("*")) {
  419                       throw new IllegalArgumentException(ResourcesMgr.getString
  420                           ("PrivateCredentialPermission.Principal.Class.can.not.be.a.wildcard.value.if.Principal.Name.is.not.a.wildcard.value"));
  421               }
  422   
  423               if (testing)
  424                   System.out.println("\tprincipalName = '" + principalName + "'");
  425   
  426               pList.add(new CredOwner(principalClass, principalName));
  427           }
  428   
  429           this.credOwners = new CredOwner[pList.size()];
  430           pList.toArray(this.credOwners);
  431       }
  432   
  433       private boolean impliesCredentialClass(String thisC, String thatC) {
  434   
  435           // this should never happen
  436           if (thisC == null || thatC == null)
  437               return false;
  438   
  439           if (testing)
  440               System.out.println("credential class comparison: " +
  441                                   thisC + "/" + thatC);
  442   
  443           if (thisC.equals("*"))
  444               return true;
  445   
  446           /**
  447            * XXX let's not enable this for now --
  448            *      if people want it, we'll enable it later
  449            */
  450           /*
  451           if (thisC.endsWith("*")) {
  452               String cClass = thisC.substring(0, thisC.length() - 2);
  453               return thatC.startsWith(cClass);
  454           }
  455           */
  456   
  457           return thisC.equals(thatC);
  458       }
  459   
  460       private boolean impliesPrincipalSet(CredOwner[] thisP, CredOwner[] thatP) {
  461   
  462           // this should never happen
  463           if (thisP == null || thatP == null)
  464               return false;
  465   
  466           if (thatP.length == 0)
  467               return true;
  468   
  469           if (thisP.length == 0)
  470               return false;
  471   
  472           for (int i = 0; i < thisP.length; i++) {
  473               boolean foundMatch = false;
  474               for (int j = 0; j < thatP.length; j++) {
  475                   if (thisP[i].implies(thatP[j])) {
  476                       foundMatch = true;
  477                       break;
  478                   }
  479               }
  480               if (!foundMatch) {
  481                   return false;
  482               }
  483           }
  484           return true;
  485       }
  486   
  487       /**
  488        * Reads this object from a stream (i.e., deserializes it)
  489        */
  490       private void readObject(java.io.ObjectInputStream s) throws
  491                                           java.io.IOException,
  492                                           ClassNotFoundException {
  493   
  494           s.defaultReadObject();
  495   
  496           // perform new initialization from the permission name
  497   
  498           if (getName().indexOf(" ") == -1 && getName().indexOf("\"") == -1) {
  499   
  500               // name only has a credential class specified
  501               credentialClass = getName();
  502               credOwners = EMPTY_PRINCIPALS;
  503   
  504           } else {
  505   
  506               // perform regular initialization
  507               init(getName());
  508           }
  509       }
  510   
  511       /**
  512        * @serial include
  513        */
  514       static class CredOwner implements java.io.Serializable {
  515   
  516           private static final long serialVersionUID = -5607449830436408266L;
  517   
  518           /**
  519            * @serial
  520            */
  521           String principalClass;
  522           /**
  523            * @serial
  524            */
  525           String principalName;
  526   
  527           CredOwner(String principalClass, String principalName) {
  528               this.principalClass = principalClass;
  529               this.principalName = principalName;
  530           }
  531   
  532           public boolean implies(Object obj) {
  533               if (obj == null || !(obj instanceof CredOwner))
  534                   return false;
  535   
  536               CredOwner that = (CredOwner)obj;
  537   
  538               if (principalClass.equals("*") ||
  539                   principalClass.equals(that.principalClass)) {
  540   
  541                   if (principalName.equals("*") ||
  542                       principalName.equals(that.principalName)) {
  543                       return true;
  544                   }
  545               }
  546   
  547               /**
  548                * XXX no code yet to support a.b.*
  549                */
  550   
  551               return false;
  552           }
  553   
  554           public String toString() {
  555               MessageFormat form = new MessageFormat(ResourcesMgr.getString
  556                   ("CredOwner.Principal.Class.class.Principal.Name.name"));
  557               Object[] source = {principalClass, principalName};
  558               return (form.format(source));
  559           }
  560       }
  561   }

Home » openjdk-7 » javax.security » auth » [javadoc | source]