KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > tanukisoftware > wrapper > security > WrapperServicePermission


1 package org.tanukisoftware.wrapper.security;
2
3 /*
4  * Copyright (c) 1999, 2006 Tanuki Software Inc.
5  *
6  * Permission is hereby granted, free of charge, to any person
7  * obtaining a copy of the Java Service Wrapper and associated
8  * documentation files (the "Software"), to deal in the Software
9  * without restriction, including without limitation the rights
10  * to use, copy, modify, merge, publish, distribute, sub-license,
11  * and/or sell copies of the Software, and to permit persons to
12  * whom the Software is furnished to do so, subject to the
13  * following conditions:
14  *
15  * The above copyright notice and this permission notice shall be
16  * included in all copies or substantial portions of the Software.
17  *
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
20  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21  * NON-INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
22  * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
23  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25  * OTHER DEALINGS IN THE SOFTWARE.
26  */

27
28 import java.security.Permission JavaDoc;
29 import java.security.PermissionCollection JavaDoc;
30 import java.util.Enumeration JavaDoc;
31 import java.util.Vector JavaDoc;
32 import java.util.StringTokenizer JavaDoc;
33
34 /**
35  * WrapperServicePermissions are used to grant the right to start, stop,
36  * pause, continue, interrogate, or send custom codes to other services
37  * running on a Windows system.
38  * <p>
39  * These permissions are inherently quite dangerous so great care should be
40  * taken when granting them. When doing so, try to only grant permission to
41  * those services which really need to be controlled.
42  * <p>
43  * The following are examples of how to specify the permission within a policy
44  * file.
45  * <pre>
46  * grant codeBase "file:../lib/-" {
47  * // Grant various permissions to a specific service.
48  * permission org.tanukisoftware.wrapper.security.WrapperServicePermission "myservice", "interrogate";
49  * permission org.tanukisoftware.wrapper.security.WrapperServicePermission "myservice", "interrogate,start,stop";
50  * permission org.tanukisoftware.wrapper.security.WrapperServicePermission "myservice", "userCode";
51  * permission org.tanukisoftware.wrapper.security.WrapperServicePermission "myservice", "*";
52  *
53  * // Grant various permissions to any service starting with "my".
54  * permission org.tanukisoftware.wrapper.security.WrapperServicePermission "my*", "*";
55  *
56  * // Let the calling code do anything to any service on the system
57  * permission org.tanukisoftware.wrapper.security.WrapperServicePermission "*", "*";
58  * permission org.tanukisoftware.wrapper.security.WrapperServicePermission "*";
59  * };
60  * </pre>
61  * <p>
62  * Possible actions include the following:
63  * <table border='1' cellpadding='2' cellspacing='0'>
64  * <tr>
65  * <th>Permission Action Name</th>
66  * <th>What the Permission Allows</th>
67  * <th>Risks of Allowing this Permission</th>
68  * </tr>
69  *
70  * <tr>
71  * <td>start</td>
72  * <td>Start a service which is installed but has not been started.</td>
73  * <td>Malicious code could potentially start any service that is not currently running.
74  * This includes services which were previously stopped or that are configured to be
75  * started manually. Many Windows systems have several services stopped by default
76  * because of the security hazards that they pose. Starting such services could open
77  * the system up to attacks related to that service.</td>
78  * </tr>
79  *
80  * <tr>
81  * <td>stop</td>
82  * <td>Stop a service which is currently running.</td>
83  * <td>Malicious code could potentially stop running service. This could result in a
84  * denial of service attack if the service is a web or database server. Or it
85  * result in more dangerous attacks if the service is a firewall or virus scanner.
86  * </td>
87  * </tr>
88  *
89  * <tr>
90  * <td>pause</td>
91  * <td>Pause a service which is currently running.</td>
92  * <td>Malicious code could potentially pause running service. This could result in a
93  * denial of service attack if the service is a web or database server. Or it
94  * result in more dangerous attacks if the service is a firewall or virus scanner.
95  * </td>
96  * </tr>
97  *
98  * <tr>
99  * <td>continue</td>
100  * <td>Continue a service which was previously paused.</td>
101  * <td>Malicious code could resume services which had been paused for a good reason.</td>
102  * </tr>
103  *
104  * <tr>
105  * <td>interrogate</td>
106  * <td>Interrogate a service as to its current state.</td>
107  * <td>Malicious code learn a lot about a system and its weakness by probing which
108  * services are currently running.</td>
109  * </tr>
110  *
111  * <tr>
112  * <td>userCode</td>
113  * <td>Send any custom user code to a service.</td>
114  * <td>The danger of this action depends on whether or not the service understands
115  * custom user codes, and what it does with them. This could potentially be a
116  * very dangerous permission to grant.</td>
117  * </tr>
118  * </table>
119  *
120  * @author Leif Mortenson <leif@tanukisoftware.com>
121  */

122 public class WrapperServicePermission
123     extends Permission JavaDoc
124 {
125     public static String JavaDoc ACTION_START = "start";
126     public static String JavaDoc ACTION_STOP = "stop";
127     public static String JavaDoc ACTION_PAUSE = "pause";
128     public static String JavaDoc ACTION_CONTINUE = "continue";
129     public static String JavaDoc ACTION_INTERROGATE = "interrogate";
130     public static String JavaDoc ACTION_USER_CODE = "userCode";
131     
132     private static int MASK_START = 1;
133     private static int MASK_STOP = 2;
134     private static int MASK_PAUSE = 4;
135     private static int MASK_CONTINUE = 8;
136     private static int MASK_INTERROGATE = 16;
137     private static int MASK_USER_CODE = 32;
138     private static int MASK_ALL =
139         MASK_START | MASK_STOP | MASK_PAUSE | MASK_CONTINUE | MASK_INTERROGATE | MASK_USER_CODE;
140     
141     private int m_actionMask;
142     
143     /*---------------------------------------------------------------
144      * Constructors
145      *-------------------------------------------------------------*/

146     /**
147      * Creates a new WrapperServicePermission for the specified service.
148      *
149      * @param serviceName The name of the service whose access is being
150      * controlled.
151      * @param actions The action or actions to be performed.
152      */

153     public WrapperServicePermission( String JavaDoc serviceName, String JavaDoc actions )
154     {
155         super( serviceName );
156         m_actionMask = buildActionMask( actions );
157     }
158     
159     /**
160      * Creates a new WrapperServicePermission for the specified service.
161      * This version of the constructor grants all actions.
162      *
163      * @param serviceName The name of the service whose access is being
164      * controlled.
165      */

166     public WrapperServicePermission( String JavaDoc serviceName )
167     {
168         this( serviceName, "*" );
169     }
170     
171     /*---------------------------------------------------------------
172      * Permission Methods
173      *-------------------------------------------------------------*/

174     /**
175      * Checks two Permission objects for equality.
176      * <p>
177      * Do not use the equals method for making access control decisions; use
178      * the implies method.
179      *
180      * @param obj The object we are testing for equality with this object.
181      *
182      * @return True if both Permission objects are equivalent.
183      */

184     public boolean equals( Object JavaDoc obj )
185     {
186         if ( obj == this )
187         {
188             return true;
189         }
190         
191         if ( !( obj instanceof WrapperServicePermission ) )
192         {
193             return false;
194         }
195         
196         WrapperServicePermission wsp = (WrapperServicePermission)obj;
197         
198         return ( m_actionMask == wsp.m_actionMask ) &&
199             getName().equals( wsp.getName() );
200     }
201     
202     /**
203      * Return the canonical string representation of the actions.
204      * Always returns present actions in the following order:
205      * start, stop, pause, continue, interrogate. userCode.
206      *
207      * @return the canonical string representation of the actions.
208      */

209     public String JavaDoc getActions()
210     {
211         StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
212         boolean first = true;
213         
214         if ( ( m_actionMask & MASK_START ) != 0 )
215         {
216             if ( first )
217             {
218                 sb.append( ',' );
219             }
220             else
221             {
222                 first = false;
223             }
224             sb.append( ACTION_START );
225         }
226         if ( ( m_actionMask & MASK_STOP ) != 0 )
227         {
228             if ( first )
229             {
230                 sb.append( ',' );
231             }
232             else
233             {
234                 first = false;
235             }
236             sb.append( ACTION_STOP );
237         }
238         if ( ( m_actionMask & MASK_PAUSE ) != 0 )
239         {
240             if ( first )
241             {
242                 sb.append( ',' );
243             }
244             else
245             {
246                 first = false;
247             }
248             sb.append( ACTION_CONTINUE );
249         }
250         if ( ( m_actionMask & MASK_CONTINUE ) != 0 )
251         {
252             if ( first )
253             {
254                 sb.append( ',' );
255             }
256             else
257             {
258                 first = false;
259             }
260             sb.append( ACTION_CONTINUE );
261         }
262         if ( ( m_actionMask & MASK_INTERROGATE ) != 0 )
263         {
264             if ( first )
265             {
266                 sb.append( ',' );
267             }
268             else
269             {
270                 first = false;
271             }
272             sb.append( ACTION_INTERROGATE );
273         }
274         if ( ( m_actionMask & MASK_USER_CODE ) != 0 )
275         {
276             if ( first )
277             {
278                 sb.append( ',' );
279             }
280             else
281             {
282                 first = false;
283             }
284             sb.append( ACTION_USER_CODE );
285         }
286         
287         return sb.toString();
288     }
289
290     /**
291      * Checks if this WrapperServicePermission object "implies" the
292      * specified permission.
293      * <P>
294      * More specifically, this method returns true if:<p>
295      * <ul>
296      * <li><i>p2</i> is an instanceof FilePermission,<p>
297      * <li><i>p2</i>'s actions are a proper subset of this object's actions,
298      * and<p>
299      * <li><i>p2</i>'s service name is implied by this object's service name.
300      * For example, "MyApp*" implies "MyApp".
301      * </ul>
302      *
303      * @param p2 the permission to check against.
304      *
305      * @return true if the specified permission is implied by this object,
306      */

307     public boolean implies( Permission JavaDoc p2 )
308     {
309         if ( !( p2 instanceof WrapperServicePermission ) )
310         {
311             return false;
312         }
313         
314         WrapperServicePermission wsp = (WrapperServicePermission)p2;
315         
316         // we get the effective mask. i.e., the "and" of this and that.
317
// They must be equal to that.mask for implies to return true.
318

319         return ( ( m_actionMask & wsp.m_actionMask ) == wsp.m_actionMask ) &&
320             impliesIgnoreActionMask( wsp );
321     }
322     
323     /**
324      * Returns an custom WSCollection implementation of a PermissionCollection.
325      */

326     public PermissionCollection JavaDoc newPermissionCollection()
327     {
328         return new WSCollection();
329     }
330
331     /**
332      * Returns the hash code value for this object.
333      *
334      * @return A hash code value for this object.
335      */

336     public int hashCode()
337     {
338         return getName().hashCode();
339     }
340     
341     /*---------------------------------------------------------------
342      * Methods
343      *-------------------------------------------------------------*/

344     /**
345      * Returns the action mask of the Permission.
346      */

347     int getActionMask()
348     {
349         return m_actionMask;
350     }
351     
352     /**
353      * Tests whether this permissions implies another without taking the
354      * action mask into account.
355      */

356     boolean impliesIgnoreActionMask( WrapperServicePermission p2 )
357     {
358         if ( getName().equals( p2.getName() ) )
359         {
360             return true;
361         }
362         
363         if ( p2.getName().endsWith( "*" ) )
364         {
365             if ( getName().startsWith( p2.getName().substring( 0, p2.getName().length() - 1 ) ) )
366             {
367                 return true;
368             }
369         }
370         return false;
371     }
372     
373     /**
374      * Builds an action mask given a comma separated list of actions.
375      */

376     private int buildActionMask( String JavaDoc actions )
377     {
378         // Check for the constants first as they are used internally.
379
if ( actions == ACTION_START )
380         {
381             return MASK_START;
382         }
383         else if ( actions == ACTION_STOP )
384         {
385             return MASK_STOP;
386         }
387         else if ( actions == ACTION_PAUSE )
388         {
389             return MASK_PAUSE;
390         }
391         else if ( actions == ACTION_CONTINUE )
392         {
393             return MASK_CONTINUE;
394         }
395         else if ( actions == ACTION_INTERROGATE )
396         {
397             return MASK_INTERROGATE;
398         }
399         else if ( actions == ACTION_USER_CODE )
400         {
401             return MASK_USER_CODE;
402         }
403         else if ( actions.equals( "*" ) )
404         {
405             return MASK_ALL;
406         }
407         
408         int mask = 0;
409         StringTokenizer JavaDoc st = new StringTokenizer JavaDoc( actions, "," );
410         while ( st.hasMoreTokens() )
411         {
412             String JavaDoc action = st.nextToken();
413             if ( action.equals( ACTION_START ) )
414             {
415                 mask |= MASK_START;
416             }
417             else if ( action.equals( ACTION_STOP ) )
418             {
419                 mask |= MASK_STOP;
420             }
421             else if ( action.equals( ACTION_PAUSE ) )
422             {
423                 mask |= MASK_PAUSE;
424             }
425             else if ( action.equals( ACTION_CONTINUE ) )
426             {
427                 mask |= MASK_CONTINUE;
428             }
429             else if ( action.equals( ACTION_INTERROGATE ) )
430             {
431                 mask |= MASK_INTERROGATE;
432             }
433             else if ( action.equals( ACTION_USER_CODE ) )
434             {
435                 mask |= MASK_USER_CODE;
436             }
437             else
438             {
439                 throw new IllegalArgumentException JavaDoc(
440                     "Invalid permission action: \"" + action + "\"" );
441             }
442         }
443         
444         return mask;
445     }
446 }
447         
448 final class WSCollection
449     extends PermissionCollection JavaDoc
450 {
451     private Vector JavaDoc m_permissions = new Vector JavaDoc();
452     
453     /*---------------------------------------------------------------
454      * Constructors
455      *-------------------------------------------------------------*/

456     /**
457      * Creates an empty WSCollection.
458      */

459     public WSCollection()
460     {
461     }
462     
463     /*---------------------------------------------------------------
464      * Methods
465      *-------------------------------------------------------------*/

466     /**
467      * Adds a permission to the FilePermissions. The key for the hash is
468      * permission.path.
469      *
470      * @param permission the Permission object to add.
471      *
472      * @exception IllegalArgumentException - if the permission is not a
473      * FilePermission
474      *
475      * @exception SecurityException - if this FilePermissionCollection object
476      * has been marked readonly
477      */

478     public void add( Permission JavaDoc permission )
479     {
480         if ( !( permission instanceof WrapperServicePermission ) )
481         {
482             throw new IllegalArgumentException JavaDoc( "invalid permission: " + permission );
483         }
484         
485         if ( isReadOnly() )
486         {
487             throw new SecurityException JavaDoc( "Collection is read-only.");
488         }
489         
490         m_permissions.add( permission );
491     }
492     
493     /**
494      * Check and see if this set of permissions implies the permissions
495      * expressed in "permission".
496      *
497      * @param permission the Permission object to compare
498      *
499      * @return true if "permission" is a proper subset of a permission in
500      * the set, false if not.
501      */

502     public boolean implies( Permission JavaDoc permission )
503     {
504         if ( !( permission instanceof WrapperServicePermission ) )
505         {
506             return false;
507         }
508
509         WrapperServicePermission wsp = (WrapperServicePermission)permission;
510         
511         int desiredMask = wsp.getActionMask();
512         int pendingMask = desiredMask;
513         int foundMask = 0;
514         
515         for ( Enumeration JavaDoc en = m_permissions.elements(); en.hasMoreElements(); )
516         {
517             WrapperServicePermission p2 =
518                 (WrapperServicePermission)en.nextElement();
519             if ( ( pendingMask & p2.getActionMask() ) != 0 )
520             {
521                 // This permission has one or more actions that we need.
522
if ( wsp.impliesIgnoreActionMask( p2 ) )
523                 {
524                     foundMask |= desiredMask & p2.getActionMask();
525                     if ( foundMask == desiredMask )
526                     {
527                         return true;
528                     }
529                     pendingMask = desiredMask ^ foundMask;
530                 }
531             }
532         }
533         
534         return false;
535     }
536
537     /**
538      * Returns an enumeration of all the WrapperServicePermission
539      * objects in the container.
540      *
541      * @return An enumeration of all the WrapperServicePermission
542      * objects.
543      */

544     public Enumeration JavaDoc elements()
545     {
546         return m_permissions.elements();
547     }
548 }
549
Popular Tags