1 /*
2  * Copyright (c) 2000, 2012, 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.rmi.rmid;
27 
28 import java.security.*;
29 import java.io.*;
30 import java.util.*;
31 
32 /**
33  * The ExecOptionPermission class represents permission for rmid to use
34  * a specific command-line option when launching an activation group.
35  * <P>
36  *
37  * @author Ann Wollrath
38  *
39  * @serial exclude
40  */
41 public final class ExecOptionPermission extends Permission
42 {
43     /**
44      * does this permission have a wildcard at the end?
45      */
46     private transient boolean wildcard;
47 
48     /**
49      * the name without the wildcard on the end
50      */
51     private transient String name;
52 
53     /**
54      * UID for serialization
55      */
56     private static final long serialVersionUID = 5842294756823092756L;
57 
ExecOptionPermission(String name)58     public ExecOptionPermission(String name) {
59         super(name);
60         init(name);
61     }
62 
ExecOptionPermission(String name, String actions)63     public ExecOptionPermission(String name, String actions) {
64         this(name);
65     }
66 
67     /**
68      * Checks if the specified permission is "implied" by
69      * this object.
70      * <P>
71      * More specifically, this method returns true if:<p>
72      * <ul>
73      * <li> <i>p</i>'s class is the same as this object's class, and<p>
74      * <li> <i>p</i>'s name equals or (in the case of wildcards)
75      *      is implied by this object's
76      *      name. For example, "a.b.*" implies "a.b.c", and
77      *      "a.b=*" implies "a.b=c"
78      * </ul>
79      *
80      * @param p the permission to check against.
81      *
82      * @return true if the passed permission is equal to or
83      * implied by this permission, false otherwise.
84      */
implies(Permission p)85     public boolean implies(Permission p) {
86         if (!(p instanceof ExecOptionPermission))
87             return false;
88 
89         ExecOptionPermission that = (ExecOptionPermission) p;
90 
91         if (this.wildcard) {
92             if (that.wildcard) {
93                 // one wildcard can imply another
94                 return that.name.startsWith(name);
95             } else {
96                 // make sure p.name is longer so a.b.* doesn't imply a.b
97                 return (that.name.length() > this.name.length()) &&
98                     that.name.startsWith(this.name);
99             }
100         } else {
101             if (that.wildcard) {
102                 // a non-wildcard can't imply a wildcard
103                 return false;
104             } else {
105                 return this.name.equals(that.name);
106             }
107         }
108     }
109 
110     /**
111      * Checks two ExecOptionPermission objects for equality.
112      * Checks that <i>obj</i>'s class is the same as this object's class
113      * and has the same name as this object.
114      * <P>
115      * @param obj the object we are testing for equality with this object.
116      * @return true if <i>obj</i> is an ExecOptionPermission, and has the same
117      * name as this ExecOptionPermission object, false otherwise.
118      */
equals(Object obj)119     public boolean equals(Object obj) {
120         if (obj == this)
121             return true;
122 
123         if ((obj == null) || (obj.getClass() != getClass()))
124             return false;
125 
126         ExecOptionPermission that = (ExecOptionPermission) obj;
127 
128         return this.getName().equals(that.getName());
129     }
130 
131 
132     /**
133      * Returns the hash code value for this object.
134      * The hash code used is the hash code of the name, that is,
135      * <code>getName().hashCode()</code>, where <code>getName</code> is
136      * from the Permission superclass.
137      *
138      * @return a hash code value for this object.
139      */
hashCode()140     public int hashCode() {
141         return this.getName().hashCode();
142     }
143 
144     /**
145      * Returns the canonical string representation of the actions.
146      *
147      * @return the canonical string representation of the actions.
148      */
getActions()149     public String getActions() {
150         return "";
151     }
152 
153     /**
154      * Returns a new PermissionCollection object for storing
155      * ExecOptionPermission objects.
156      * <p>
157      * A ExecOptionPermissionCollection stores a collection of
158      * ExecOptionPermission permissions.
159      *
160      * <p>ExecOptionPermission objects must be stored in a manner that allows
161      * them to be inserted in any order, but that also enables the
162      * PermissionCollection <code>implies</code> method
163      * to be implemented in an efficient (and consistent) manner.
164      *
165      * @return a new PermissionCollection object suitable for
166      * storing ExecOptionPermissions.
167      */
newPermissionCollection()168     public PermissionCollection newPermissionCollection() {
169         return new ExecOptionPermissionCollection();
170     }
171 
172     /**
173      * readObject is called to restore the state of the ExecOptionPermission
174      * from a stream.
175      */
readObject(java.io.ObjectInputStream s)176     private synchronized void readObject(java.io.ObjectInputStream s)
177          throws IOException, ClassNotFoundException
178     {
179         s.defaultReadObject();
180         // init is called to initialize the rest of the values.
181         init(getName());
182     }
183 
184     /**
185      * Initialize a ExecOptionPermission object. Common to all constructors.
186      * Also called during de-serialization.
187      */
init(String name)188     private void init(String name)
189     {
190         if (name == null)
191             throw new NullPointerException("name can't be null");
192 
193         if (name.equals("")) {
194             throw new IllegalArgumentException("name can't be empty");
195         }
196 
197         if (name.endsWith(".*") || name.endsWith("=*") || name.equals("*")) {
198             wildcard = true;
199             if (name.length() == 1) {
200                 this.name = "";
201             } else {
202                 this.name = name.substring(0, name.length()-1);
203             }
204         } else {
205             this.name = name;
206         }
207     }
208 
209     /**
210      * A ExecOptionPermissionCollection stores a collection
211      * of ExecOptionPermission permissions. ExecOptionPermission objects
212      * must be stored in a manner that allows them to be inserted in any
213      * order, but enable the implies function to evaluate the implies
214      * method in an efficient (and consistent) manner.
215      *
216      * A ExecOptionPermissionCollection handles comparing a permission like
217      * "a.b.c.d.e" * with a Permission such as "a.b.*", or "*".
218      *
219      * @serial include
220      */
221     private static class ExecOptionPermissionCollection
222         extends PermissionCollection
223         implements java.io.Serializable
224     {
225 
226         private Hashtable<String, Permission> permissions;
227         private boolean all_allowed; // true if "*" is in the collection
228         private static final long serialVersionUID = -1242475729790124375L;
229 
230         /**
231          * Create an empty ExecOptionPermissionCollection.
232          */
ExecOptionPermissionCollection()233         public ExecOptionPermissionCollection() {
234             permissions = new Hashtable<>(11);
235             all_allowed = false;
236         }
237 
238         /**
239          * Adds a permission to the collection. The key for the hash is
240          * permission.name.
241          *
242          * @param permission the Permission object to add.
243          *
244          * @exception IllegalArgumentException - if the permission is not a
245          *                                       ExecOptionPermission
246          *
247          * @exception SecurityException - if this ExecOptionPermissionCollection
248          *                                object has been marked readonly
249          */
250 
add(Permission permission)251         public void add(Permission permission)
252         {
253             if (! (permission instanceof ExecOptionPermission))
254                 throw new IllegalArgumentException("invalid permission: "+
255                                                    permission);
256             if (isReadOnly())
257                 throw new SecurityException("attempt to add a Permission to a readonly PermissionCollection");
258 
259             ExecOptionPermission p = (ExecOptionPermission) permission;
260 
261             permissions.put(p.getName(), permission);
262             if (!all_allowed) {
263                 if (p.getName().equals("*"))
264                     all_allowed = true;
265             }
266         }
267 
268         /**
269          * Check and see if this set of permissions implies the permissions
270          * expressed in "permission".
271          *
272          * @param p the Permission object to compare
273          *
274          * @return true if "permission" is a proper subset of a permission in
275          * the set, false if not.
276          */
implies(Permission permission)277         public boolean implies(Permission permission)
278         {
279             if (! (permission instanceof ExecOptionPermission))
280                 return false;
281 
282             ExecOptionPermission p = (ExecOptionPermission) permission;
283 
284             // short circuit if the "*" Permission was added
285             if (all_allowed)
286                 return true;
287 
288             // strategy:
289             // Check for full match first. Then work our way up the
290             // name looking for matches on a.b.*
291 
292             String pname = p.getName();
293 
294             Permission x = permissions.get(pname);
295 
296             if (x != null)
297                 // we have a direct hit!
298                 return x.implies(permission);
299 
300 
301             // work our way up the tree...
302             int last, offset;
303 
304             offset = pname.length() - 1;
305 
306             while ((last = pname.lastIndexOf(".", offset)) != -1) {
307 
308                 pname = pname.substring(0, last+1) + "*";
309                 x = permissions.get(pname);
310 
311                 if (x != null) {
312                     return x.implies(permission);
313                 }
314                 offset = last - 1;
315             }
316 
317             // check for "=*" wildcard match
318             pname = p.getName();
319             offset = pname.length() - 1;
320 
321             while ((last = pname.lastIndexOf("=", offset)) != -1) {
322 
323                 pname = pname.substring(0, last+1) + "*";
324                 x = permissions.get(pname);
325 
326                 if (x != null) {
327                     return x.implies(permission);
328                 }
329                 offset = last - 1;
330             }
331 
332             // we don't have to check for "*" as it was already checked
333             // at the top (all_allowed), so we just return false
334             return false;
335         }
336 
337         /**
338          * Returns an enumeration of all the ExecOptionPermission objects in the
339          * container.
340          *
341          * @return an enumeration of all the ExecOptionPermission objects.
342          */
343 
elements()344         public Enumeration<Permission> elements()
345         {
346             return permissions.elements();
347         }
348     }
349 }
350