KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > javax > security > auth > PrivateCredentialPermission


1 /*
2  * @(#)PrivateCredentialPermission.java 1.31 03/12/19
3  *
4  * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
5  * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
6  */

7
8 package javax.security.auth;
9
10 import java.util.*;
11 import java.text.MessageFormat JavaDoc;
12 import java.security.Permission JavaDoc;
13 import java.security.PermissionCollection JavaDoc;
14 import java.security.Principal JavaDoc;
15 import sun.security.util.ResourcesMgr;
16
17 /**
18  * This class is used to protect access to private Credentials
19  * belonging to a particular <code>Subject</code>. The <code>Subject</code>
20  * is represented by a Set of Principals.
21  *
22  * <p> The target name of this <code>Permission</code> specifies
23  * a Credential class name, and a Set of Principals.
24  * The only valid value for this Permission's actions is, "read".
25  * The target name must abide by the following syntax:
26  *
27  * <pre>
28  * CredentialClass {PrincipalClass "PrincipalName"}*
29  * </pre>
30  *
31  * For example, the following permission grants access to the
32  * com.sun.PrivateCredential owned by Subjects which have
33  * a com.sun.Principal with the name, "duke". Note that although
34  * this example, as well as all the examples below, do not contain
35  * Codebase, SignedBy, or Principal information in the grant statement
36  * (for simplicity reasons), actual policy configurations should
37  * specify that information when appropriate.
38  *
39  * <pre>
40  *
41  * grant {
42  * permission javax.security.auth.PrivateCredentialPermission
43  * "com.sun.PrivateCredential com.sun.Principal \"duke\"",
44  * "read";
45  * };
46  * </pre>
47  *
48  * If CredentialClass is "*", then access is granted to
49  * all private Credentials belonging to the specified
50  * <code>Subject</code>.
51  * If "PrincipalName" is "*", then access is granted to the
52  * specified Credential owned by any <code>Subject</code> that has the
53  * specified <code>Principal</code> (the actual PrincipalName doesn't matter).
54  * For example, the following grants access to the
55  * a.b.Credential owned by any <code>Subject</code> that has
56  * an a.b.Principal.
57  *
58  * <pre>
59  * grant {
60  * permission javax.security.auth.PrivateCredentialPermission
61  * "a.b.Credential a.b.Principal "*"",
62  * "read";
63  * };
64  * </pre>
65  *
66  * If both the PrincipalClass and "PrincipalName" are "*",
67  * then access is granted to the specified Credential owned by
68  * any <code>Subject</code>.
69  *
70  * <p> In addition, the PrincipalClass/PrincipalName pairing may be repeated:
71  *
72  * <pre>
73  * grant {
74  * permission javax.security.auth.PrivateCredentialPermission
75  * "a.b.Credential a.b.Principal "duke" c.d.Principal "dukette"",
76  * "read";
77  * };
78  * </pre>
79  *
80  * The above grants access to the private Credential, "a.b.Credential",
81  * belonging to a <code>Subject</code> with at least two associated Principals:
82  * "a.b.Principal" with the name, "duke", and "c.d.Principal", with the name,
83  * "dukette".
84  *
85  * @version 1.31, 12/19/03
86  */

87 public final class PrivateCredentialPermission extends Permission JavaDoc {
88
89     private static final long serialVersionUID = 5284372143517237068L;
90
91     private static final CredOwner[] EMPTY_PRINCIPALS = new CredOwner[0];
92
93     /**
94      * @serial
95      */

96     private String JavaDoc credentialClass;
97
98     /**
99      * @serial The Principals associated with this permission.
100      * The set contains elements of type,
101      * <code>PrivateCredentialPermission.CredOwner</code>.
102      */

103     private Set principals; // ignored - kept around for compatibility
104
private transient CredOwner[] credOwners;
105
106     /**
107      * @serial
108      */

109     private boolean testing = false;
110
111     /**
112      * Create a new <code>PrivateCredentialPermission</code>
113      * with the specified <code>credentialClass</code> and Principals.
114      */

115     PrivateCredentialPermission(String JavaDoc credentialClass, Set principals) {
116     super(credentialClass);
117     this.credentialClass = credentialClass;
118
119     synchronized(principals) {
120         if (principals.size() == 0) {
121         this.credOwners = EMPTY_PRINCIPALS;
122         } else {
123         this.credOwners = new CredOwner[principals.size()];
124         int index = 0;
125         Iterator i = principals.iterator();
126         while (i.hasNext()) {
127             Principal JavaDoc p = (Principal JavaDoc)i.next();
128             this.credOwners[index++] = new CredOwner
129                         (p.getClass().getName(),
130                         p.getName());
131         }
132         }
133     }
134     }
135
136     /**
137      * Creates a new <code>PrivateCredentialPermission</code>
138      * with the specified <code>name</code>. The <code>name</code>
139      * specifies both a Credential class and a <code>Principal</code> Set.
140      *
141      * <p>
142      *
143      * @param name the name specifying the Credential class and
144      * <code>Principal</code> Set. <p>
145      *
146      * @param actions the actions specifying that the Credential can be read.
147      *
148      * @throws IllegalArgumentException if <code>name</code> does not conform
149      * to the correct syntax or if <code>actions</code> is not "read".
150      */

151     public PrivateCredentialPermission(String JavaDoc name, String JavaDoc actions) {
152     super(name);
153
154     if (!"read".equalsIgnoreCase(actions))
155         throw new IllegalArgumentException JavaDoc
156         (ResourcesMgr.getString("actions can only be 'read'"));
157     init(name);
158     }
159
160     /**
161      * Returns the Class name of the Credential associated with this
162      * <code>PrivateCredentialPermission</code>.
163      *
164      * <p>
165      *
166      * @return the Class name of the Credential associated with this
167      * <code>PrivateCredentialPermission</code>.
168      */

169     public String JavaDoc getCredentialClass() {
170     return credentialClass;
171     }
172
173     /**
174      * Returns the <code>Principal</code> classes and names
175      * associated with this <code>PrivateCredentialPermission</code>.
176      * The information is returned as a two-dimensional array (array[x][y]).
177      * The 'x' value corresponds to the number of <code>Principal</code>
178      * class and name pairs. When (y==0), it corresponds to
179      * the <code>Principal</code> class value, and when (y==1),
180      * it corresponds to the <code>Principal</code> name value.
181      * For example, array[0][0] corresponds to the class name of
182      * the first <code>Principal</code> in the array. array[0][1]
183      * corresponds to the <code>Principal</code> name of the
184      * first <code>Principal</code> in the array.
185      *
186      * <p>
187      *
188      * @return the <code>Principal</code> class and names associated
189      * with this <code>PrivateCredentialPermission</code>.
190      */

191     public String JavaDoc[][] getPrincipals() {
192
193     if (credOwners == null || credOwners.length == 0) {
194         return new String JavaDoc[0][0];
195     }
196
197     String JavaDoc[][] pArray = new String JavaDoc[credOwners.length][2];
198     for (int i = 0; i < credOwners.length; i++) {
199         pArray[i][0] = credOwners[i].principalClass;
200         pArray[i][1] = credOwners[i].principalName;
201     }
202     return pArray;
203     }
204
205     /**
206      * Checks if this <code>PrivateCredentialPermission</code> implies
207      * the specified <code>Permission</code>.
208      *
209      * <p>
210      *
211      * This method returns true if:
212      * <p><ul>
213      * <li> <i>p</i> is an instanceof PrivateCredentialPermission and <p>
214      * <li> the target name for <i>p</i> is implied by this object's
215      * target name. For example:
216      * <pre>
217      * [* P1 "duke"] implies [a.b.Credential P1 "duke"].
218      * [C1 P1 "duke"] implies [C1 P1 "duke" P2 "dukette"].
219      * [C1 P2 "dukette"] implies [C1 P1 "duke" P2 "dukette"].
220      * </pre>
221      * </ul>
222      *
223      * <p>
224      *
225      * @param p the <code>Permission</code> to check against.
226      *
227      * @return true if this <code>PrivateCredentialPermission</code> implies
228      * the specified <code>Permission</code>, false if not.
229      */

230     public boolean implies(Permission JavaDoc p) {
231
232     if (p == null || !(p instanceof PrivateCredentialPermission JavaDoc))
233         return false;
234
235     PrivateCredentialPermission JavaDoc that = (PrivateCredentialPermission JavaDoc)p;
236
237     if (!impliesCredentialClass(credentialClass, that.credentialClass))
238         return false;
239
240     return impliesPrincipalSet(credOwners, that.credOwners);
241     }
242
243     /**
244      * Checks two <code>PrivateCredentialPermission</code> objects for
245      * equality. Checks that <i>obj</i> is a
246      * <code>PrivateCredentialPermission</code>,
247      * and has the same credential class as this object,
248      * as well as the same Principals as this object.
249      * The order of the Principals in the respective Permission's
250      * target names is not relevant.
251      *
252      * <p>
253      *
254      * @param obj the object we are testing for equality with this object.
255      *
256      * @return true if obj is a <code>PrivateCredentialPermission</code>,
257      * has the same credential class as this object,
258      * and has the same Principals as this object.
259      */

260     public boolean equals(Object JavaDoc obj) {
261         if (obj == this)
262             return true;
263
264         if (! (obj instanceof PrivateCredentialPermission JavaDoc))
265             return false;
266
267         PrivateCredentialPermission JavaDoc that = (PrivateCredentialPermission JavaDoc)obj;
268
269     return (this.implies(that) && that.implies(this));
270     }
271
272     /**
273      * Returns the hash code value for this object.
274      *
275      * @return a hash code value for this object.
276      */

277     public int hashCode() {
278         return this.credentialClass.hashCode();
279     }
280
281     /**
282      * Returns the "canonical string representation" of the actions.
283      * This method always returns the String, "read".
284      *
285      * <p>
286      *
287      * @return the actions (always returns "read").
288      */

289     public String JavaDoc getActions() {
290     return "read";
291     }
292
293     /**
294      * Return a homogeneous collection of PrivateCredentialPermissions
295      * in a <code>PermissionCollection</code>.
296      * No such <code>PermissionCollection</code> is defined,
297      * so this method always returns <code>null</code>.
298      *
299      * <p>
300      *
301      * @return null in all cases.
302      */

303     public PermissionCollection JavaDoc newPermissionCollection() {
304     return null;
305     }
306
307     private void init(String JavaDoc name) {
308
309     if (name == null || name.trim().length() == 0) {
310         throw new IllegalArgumentException JavaDoc("invalid empty name");
311     }
312
313     ArrayList pList = new ArrayList();
314     StringTokenizer tokenizer = new StringTokenizer(name, " ", true);
315     String JavaDoc principalClass = null;
316     String JavaDoc principalName = null;
317
318     if (testing)
319         System.out.println("whole name = " + name);
320
321     // get the Credential Class
322
credentialClass = tokenizer.nextToken();
323     if (testing)
324         System.out.println("Credential Class = " + credentialClass);
325
326     if (tokenizer.hasMoreTokens() == false) {
327         MessageFormat JavaDoc form = new MessageFormat JavaDoc(ResourcesMgr.getString
328         ("permission name [name] syntax invalid: "));
329         Object JavaDoc[] source = {name};
330         throw new IllegalArgumentException JavaDoc
331         (form.format(source) + ResourcesMgr.getString
332             ("Credential Class not followed by a " +
333             "Principal Class and Name"));
334     }
335
336     while (tokenizer.hasMoreTokens()) {
337
338         // skip delimiter
339
tokenizer.nextToken();
340
341         // get the Principal Class
342
principalClass = tokenizer.nextToken();
343         if (testing)
344         System.out.println(" Principal Class = " + principalClass);
345
346         if (tokenizer.hasMoreTokens() == false) {
347         MessageFormat JavaDoc form = new MessageFormat JavaDoc(ResourcesMgr.getString
348             ("permission name [name] syntax invalid: "));
349         Object JavaDoc[] source = {name};
350         throw new IllegalArgumentException JavaDoc
351             (form.format(source) + ResourcesMgr.getString
352             ("Principal Class not followed by a Principal Name"));
353         }
354
355         // skip delimiter
356
tokenizer.nextToken();
357
358         // get the Principal Name
359
principalName = tokenizer.nextToken();
360
361         if (!principalName.startsWith("\"")) {
362         MessageFormat JavaDoc form = new MessageFormat JavaDoc(ResourcesMgr.getString
363             ("permission name [name] syntax invalid: "));
364         Object JavaDoc[] source = {name};
365         throw new IllegalArgumentException JavaDoc
366             (form.format(source) + ResourcesMgr.getString
367             ("Principal Name must be surrounded by quotes"));
368         }
369
370         if (!principalName.endsWith("\"")) {
371
372         // we have a name with spaces in it --
373
// keep parsing until we find the end quote,
374
// and keep the spaces in the name
375

376         while (tokenizer.hasMoreTokens()) {
377             principalName = principalName + tokenizer.nextToken();
378             if (principalName.endsWith("\""))
379             break;
380         }
381
382         if (!principalName.endsWith("\"")) {
383             MessageFormat JavaDoc form = new MessageFormat JavaDoc
384             (ResourcesMgr.getString
385             ("permission name [name] syntax invalid: "));
386             Object JavaDoc[] source = {name};
387             throw new IllegalArgumentException JavaDoc
388             (form.format(source) + ResourcesMgr.getString
389                 ("Principal Name missing end quote"));
390         }
391         }
392
393         if (testing)
394         System.out.println("\tprincipalName = '" + principalName + "'");
395
396         principalName = principalName.substring
397                     (1, principalName.length() - 1);
398
399         if (principalClass.equals("*") &&
400         !principalName.equals("*")) {
401             throw new IllegalArgumentException JavaDoc(ResourcesMgr.getString
402             ("PrivateCredentialPermission Principal Class " +
403             "can not be a wildcard (*) value if Principal Name " +
404             "is not a wildcard (*) value"));
405         }
406
407         if (testing)
408         System.out.println("\tprincipalName = '" + principalName + "'");
409
410         pList.add(new CredOwner(principalClass, principalName));
411     }
412
413     this.credOwners = new CredOwner[pList.size()];
414     pList.toArray((CredOwner[])this.credOwners);
415     }
416
417     private boolean impliesCredentialClass(String JavaDoc thisC, String JavaDoc thatC) {
418
419     // this should never happen
420
if (thisC == null || thatC == null)
421         return false;
422
423     if (testing)
424         System.out.println("credential class comparison: " +
425                 thisC + "/" + thatC);
426
427     if (thisC.equals("*"))
428         return true;
429
430     /**
431      * XXX let's not enable this for now --
432      * if people want it, we'll enable it later
433      */

434     /*
435     if (thisC.endsWith("*")) {
436         String cClass = thisC.substring(0, thisC.length() - 2);
437         return thatC.startsWith(cClass);
438     }
439     */

440
441     return thisC.equals(thatC);
442     }
443
444     private boolean impliesPrincipalSet(CredOwner[] thisP, CredOwner[] thatP) {
445
446     // this should never happen
447
if (thisP == null || thatP == null)
448         return false;
449
450     if (thatP.length == 0)
451         return true;
452
453     if (thisP.length == 0)
454         return false;
455
456     for (int i = 0; i < thisP.length; i++) {
457         boolean foundMatch = false;
458         for (int j = 0; j < thatP.length; j++) {
459         if (thisP[i].implies(thatP[j])) {
460             foundMatch = true;
461             break;
462         }
463         }
464         if (!foundMatch) {
465         return false;
466         }
467     }
468     return true;
469     }
470
471     /**
472      * Reads this object from a stream (i.e., deserializes it)
473      */

474     private void readObject(java.io.ObjectInputStream JavaDoc s) throws
475                     java.io.IOException JavaDoc,
476                     ClassNotFoundException JavaDoc {
477
478         s.defaultReadObject();
479
480         // perform new initialization from the permission name
481

482         if (getName().indexOf(" ") == -1 && getName().indexOf("\"") == -1) {
483
484         // name only has a credential class specified
485
credentialClass = getName();
486         credOwners = EMPTY_PRINCIPALS;
487
488         } else {
489
490         // perform regular initialization
491
init(getName());
492         }
493     }
494
495     /**
496      * @serial include
497      */

498     static class CredOwner implements java.io.Serializable JavaDoc {
499
500     private static final long serialVersionUID = -5607449830436408266L;
501
502     /**
503      * @serial
504      */

505     String JavaDoc principalClass;
506     /**
507      * @serial
508      */

509     String JavaDoc principalName;
510
511     CredOwner(String JavaDoc principalClass, String JavaDoc principalName) {
512         this.principalClass = principalClass;
513         this.principalName = principalName;
514     }
515
516     public boolean implies(Object JavaDoc obj) {
517         if (obj == null || !(obj instanceof CredOwner))
518         return false;
519
520         CredOwner that = (CredOwner)obj;
521
522         if (principalClass.equals("*") ||
523         principalClass.equals(that.principalClass)) {
524
525         if (principalName.equals("*") ||
526             principalName.equals(that.principalName)) {
527             return true;
528         }
529         }
530
531         /**
532          * XXX no code yet to support a.b.*
533          */

534
535         return false;
536     }
537
538     public String JavaDoc toString() {
539         MessageFormat JavaDoc form = new MessageFormat JavaDoc(ResourcesMgr.getString
540         ("CredOwner:\n\tPrincipal Class = class\n\t" +
541             "Principal Name = name"));
542         Object JavaDoc[] source = {principalClass, principalName};
543         return (form.format(source));
544     }
545     }
546 }
547
Popular Tags