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