KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sun > jmx > remote > security > MBeanServerAccessController


1 /*
2  * @(#)MBeanServerAccessController.java 1.8 06/06/29
3  *
4  * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
5  * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
6  */

7
8 package com.sun.jmx.remote.security;
9
10 import com.sun.jmx.mbeanserver.GetPropertyAction;
11 import java.io.ObjectInputStream JavaDoc;
12 import java.security.AccessController JavaDoc;
13 import java.util.Set JavaDoc;
14 import javax.management.Attribute JavaDoc;
15 import javax.management.AttributeList JavaDoc;
16 import javax.management.AttributeNotFoundException JavaDoc;
17 import javax.management.InstanceNotFoundException JavaDoc;
18 import javax.management.InstanceAlreadyExistsException JavaDoc;
19 import javax.management.IntrospectionException JavaDoc;
20 import javax.management.InvalidAttributeValueException JavaDoc;
21 import javax.management.ListenerNotFoundException JavaDoc;
22 import javax.management.MBeanException JavaDoc;
23 import javax.management.MBeanInfo JavaDoc;
24 import javax.management.MBeanRegistrationException JavaDoc;
25 import javax.management.MBeanServer JavaDoc;
26 import javax.management.NotCompliantMBeanException JavaDoc;
27 import javax.management.NotificationFilter JavaDoc;
28 import javax.management.NotificationListener JavaDoc;
29 import javax.management.ObjectInstance JavaDoc;
30 import javax.management.ObjectName JavaDoc;
31 import javax.management.OperationsException JavaDoc;
32 import javax.management.QueryExp JavaDoc;
33 import javax.management.ReflectionException JavaDoc;
34 import javax.management.loading.ClassLoaderRepository JavaDoc;
35 import javax.management.remote.MBeanServerForwarder JavaDoc;
36
37 /**
38  * <p>An object of this class implements the MBeanServer interface
39  * and, for each of its methods, calls an appropriate checking method
40  * and then forwards the request to a wrapped MBeanServer object. The
41  * checking method may throw a RuntimeException if the operation is
42  * not allowed; in this case the request is not forwarded to the
43  * wrapped object.</p>
44  *
45  * <p>A typical use of this class is to insert it between a connector server
46  * such as the RMI connector and the MBeanServer with which the connector
47  * is associated. Requests from the connector client can then be filtered
48  * and those operations that are not allowed, or not allowed in a particular
49  * context, can be rejected by throwing a <code>SecurityException</code>
50  * in the corresponding <code>check*</code> method.</p>
51  *
52  * <p>This is an abstract class, because in its implementation none of
53  * the checking methods does anything. To be useful, it must be
54  * subclassed and at least one of the checking methods overridden to
55  * do some checking. Some or all of the MBeanServer methods may also
56  * be overridden, for instance if the default checking behavior is
57  * inappropriate.</p>
58  *
59  * <p>If there is no SecurityManager, then the access controller will refuse
60  * to create an MBean that is a ClassLoader, which includes MLets, or to
61  * execute the method addURL on an MBean that is an MLet. This prevents
62  * people from opening security holes unintentionally. Otherwise, it
63  * would not be obvious that granting write access grants the ability to
64  * download and execute arbitrary code in the target MBean server. Advanced
65  * users who do want the ability to use MLets are presumably advanced enough
66  * to handle policy files and security managers.</p>
67  */

68 public abstract class MBeanServerAccessController
69     implements MBeanServerForwarder JavaDoc {
70
71     public MBeanServer JavaDoc getMBeanServer() {
72     return mbs;
73     }
74
75     public void setMBeanServer(MBeanServer JavaDoc mbs) {
76     if (mbs == null)
77         throw new IllegalArgumentException JavaDoc("Null MBeanServer");
78     if (this.mbs != null)
79         throw new IllegalArgumentException JavaDoc("MBeanServer object already " +
80                            "initialized");
81     this.mbs = mbs;
82     }
83
84     /**
85      * Check if the caller can do read operations. This method does
86      * nothing if so, otherwise throws SecurityException.
87      */

88     protected abstract void checkRead();
89
90     /**
91      * Check if the caller can do write operations. This method does
92      * nothing if so, otherwise throws SecurityException.
93      */

94     protected abstract void checkWrite();
95
96     //--------------------------------------------
97
//--------------------------------------------
98
//
99
// Implementation of the MBeanServer interface
100
//
101
//--------------------------------------------
102
//--------------------------------------------
103

104     /**
105      * Call <code>checkRead()</code>, then forward this method to the
106      * wrapped object.
107      */

108     public void addNotificationListener(ObjectName JavaDoc name,
109                     NotificationListener JavaDoc listener,
110                     NotificationFilter JavaDoc filter,
111                     Object JavaDoc handback)
112     throws InstanceNotFoundException JavaDoc {
113     checkRead();
114     getMBeanServer().addNotificationListener(name, listener,
115                          filter, handback);
116     }
117
118     /**
119      * Call <code>checkRead()</code>, then forward this method to the
120      * wrapped object.
121      */

122     public void addNotificationListener(ObjectName JavaDoc name,
123                     ObjectName JavaDoc listener,
124                     NotificationFilter JavaDoc filter,
125                     Object JavaDoc handback)
126     throws InstanceNotFoundException JavaDoc {
127     checkRead();
128     getMBeanServer().addNotificationListener(name, listener,
129                          filter, handback);
130     }
131
132     /**
133      * Call <code>checkWrite()</code>, then forward this method to the
134      * wrapped object.
135      */

136     public ObjectInstance JavaDoc createMBean(String JavaDoc className, ObjectName JavaDoc name)
137     throws
138     ReflectionException JavaDoc,
139     InstanceAlreadyExistsException JavaDoc,
140     MBeanRegistrationException JavaDoc,
141     MBeanException JavaDoc,
142     NotCompliantMBeanException JavaDoc {
143     checkWrite();
144     SecurityManager JavaDoc sm = System.getSecurityManager();
145     if (sm == null) {
146         Object JavaDoc object = getMBeanServer().instantiate(className);
147         checkClassLoader(object);
148         return getMBeanServer().registerMBean(object, name);
149     } else {
150         return getMBeanServer().createMBean(className, name);
151     }
152     }
153
154     /**
155      * Call <code>checkWrite()</code>, then forward this method to the
156      * wrapped object.
157      */

158     public ObjectInstance JavaDoc createMBean(String JavaDoc className, ObjectName JavaDoc name,
159                       Object JavaDoc params[], String JavaDoc signature[])
160     throws
161     ReflectionException JavaDoc,
162     InstanceAlreadyExistsException JavaDoc,
163     MBeanRegistrationException JavaDoc,
164     MBeanException JavaDoc,
165     NotCompliantMBeanException JavaDoc {
166     checkWrite();
167     SecurityManager JavaDoc sm = System.getSecurityManager();
168     if (sm == null) {
169         Object JavaDoc object = getMBeanServer().instantiate(className,
170                              params,
171                              signature);
172         checkClassLoader(object);
173         return getMBeanServer().registerMBean(object, name);
174     } else {
175         return getMBeanServer().createMBean(className, name,
176                         params, signature);
177     }
178     }
179
180     /**
181      * Call <code>checkWrite()</code>, then forward this method to the
182      * wrapped object.
183      */

184     public ObjectInstance JavaDoc createMBean(String JavaDoc className,
185                       ObjectName JavaDoc name,
186                       ObjectName JavaDoc loaderName)
187     throws
188     ReflectionException JavaDoc,
189     InstanceAlreadyExistsException JavaDoc,
190     MBeanRegistrationException JavaDoc,
191     MBeanException JavaDoc,
192     NotCompliantMBeanException JavaDoc,
193     InstanceNotFoundException JavaDoc {
194     checkWrite();
195     SecurityManager JavaDoc sm = System.getSecurityManager();
196     if (sm == null) {
197         Object JavaDoc object = getMBeanServer().instantiate(className,
198                              loaderName);
199         checkClassLoader(object);
200         return getMBeanServer().registerMBean(object, name);
201     } else {
202         return getMBeanServer().createMBean(className, name, loaderName);
203     }
204     }
205
206     /**
207      * Call <code>checkWrite()</code>, then forward this method to the
208      * wrapped object.
209      */

210     public ObjectInstance JavaDoc createMBean(String JavaDoc className,
211                       ObjectName JavaDoc name,
212                       ObjectName JavaDoc loaderName,
213                       Object JavaDoc params[],
214                       String JavaDoc signature[])
215     throws
216     ReflectionException JavaDoc,
217     InstanceAlreadyExistsException JavaDoc,
218     MBeanRegistrationException JavaDoc,
219     MBeanException JavaDoc,
220     NotCompliantMBeanException JavaDoc,
221     InstanceNotFoundException JavaDoc {
222     checkWrite();
223     SecurityManager JavaDoc sm = System.getSecurityManager();
224     if (sm == null) {
225         Object JavaDoc object = getMBeanServer().instantiate(className,
226                              loaderName,
227                              params,
228                              signature);
229         checkClassLoader(object);
230         return getMBeanServer().registerMBean(object, name);
231     } else {
232         return getMBeanServer().createMBean(className, name, loaderName,
233                         params, signature);
234     }
235     }
236
237     /**
238      * Call <code>checkRead()</code>, then forward this method to the
239      * wrapped object.
240      */

241     public ObjectInputStream JavaDoc deserialize(ObjectName JavaDoc name, byte[] data)
242     throws InstanceNotFoundException JavaDoc, OperationsException JavaDoc {
243     checkRead();
244     return getMBeanServer().deserialize(name, data);
245     }
246
247     /**
248      * Call <code>checkRead()</code>, then forward this method to the
249      * wrapped object.
250      */

251     public ObjectInputStream JavaDoc deserialize(String JavaDoc className, byte[] data)
252     throws OperationsException JavaDoc, ReflectionException JavaDoc {
253     checkRead();
254     return getMBeanServer().deserialize(className, data);
255     }
256
257     /**
258      * Call <code>checkRead()</code>, then forward this method to the
259      * wrapped object.
260      */

261     public ObjectInputStream JavaDoc deserialize(String JavaDoc className,
262                      ObjectName JavaDoc loaderName,
263                      byte[] data)
264     throws
265     InstanceNotFoundException JavaDoc,
266     OperationsException JavaDoc,
267     ReflectionException JavaDoc {
268     checkRead();
269     return getMBeanServer().deserialize(className, loaderName, data);
270     }
271
272     /**
273      * Call <code>checkRead()</code>, then forward this method to the
274      * wrapped object.
275      */

276     public Object JavaDoc getAttribute(ObjectName JavaDoc name, String JavaDoc attribute)
277     throws
278     MBeanException JavaDoc,
279     AttributeNotFoundException JavaDoc,
280     InstanceNotFoundException JavaDoc,
281     ReflectionException JavaDoc {
282     checkRead();
283     return getMBeanServer().getAttribute(name, attribute);
284     }
285
286     /**
287      * Call <code>checkRead()</code>, then forward this method to the
288      * wrapped object.
289      */

290     public AttributeList JavaDoc getAttributes(ObjectName JavaDoc name, String JavaDoc[] attributes)
291     throws InstanceNotFoundException JavaDoc, ReflectionException JavaDoc {
292     checkRead();
293     return getMBeanServer().getAttributes(name, attributes);
294     }
295
296     /**
297      * Call <code>checkRead()</code>, then forward this method to the
298      * wrapped object.
299      */

300     public ClassLoader JavaDoc getClassLoader(ObjectName JavaDoc loaderName)
301     throws InstanceNotFoundException JavaDoc {
302     checkRead();
303     return getMBeanServer().getClassLoader(loaderName);
304     }
305
306     /**
307      * Call <code>checkRead()</code>, then forward this method to the
308      * wrapped object.
309      */

310     public ClassLoader JavaDoc getClassLoaderFor(ObjectName JavaDoc mbeanName)
311     throws InstanceNotFoundException JavaDoc {
312     checkRead();
313     return getMBeanServer().getClassLoaderFor(mbeanName);
314     }
315
316     /**
317      * Call <code>checkRead()</code>, then forward this method to the
318      * wrapped object.
319      */

320     public ClassLoaderRepository JavaDoc getClassLoaderRepository() {
321     checkRead();
322     return getMBeanServer().getClassLoaderRepository();
323     }
324
325     /**
326      * Call <code>checkRead()</code>, then forward this method to the
327      * wrapped object.
328      */

329     public String JavaDoc getDefaultDomain() {
330     checkRead();
331     return getMBeanServer().getDefaultDomain();
332     }
333
334     /**
335      * Call <code>checkRead()</code>, then forward this method to the
336      * wrapped object.
337      */

338     public String JavaDoc[] getDomains() {
339     checkRead();
340     return getMBeanServer().getDomains();
341     }
342
343     /**
344      * Call <code>checkRead()</code>, then forward this method to the
345      * wrapped object.
346      */

347     public Integer JavaDoc getMBeanCount() {
348     checkRead();
349     return getMBeanServer().getMBeanCount();
350     }
351
352     /**
353      * Call <code>checkRead()</code>, then forward this method to the
354      * wrapped object.
355      */

356     public MBeanInfo JavaDoc getMBeanInfo(ObjectName JavaDoc name)
357     throws
358     InstanceNotFoundException JavaDoc,
359     IntrospectionException JavaDoc,
360     ReflectionException JavaDoc {
361     checkRead();
362     return getMBeanServer().getMBeanInfo(name);
363     }
364
365     /**
366      * Call <code>checkRead()</code>, then forward this method to the
367      * wrapped object.
368      */

369     public ObjectInstance JavaDoc getObjectInstance(ObjectName JavaDoc name)
370     throws InstanceNotFoundException JavaDoc {
371     checkRead();
372     return getMBeanServer().getObjectInstance(name);
373     }
374
375     /**
376      * Call <code>checkWrite()</code>, then forward this method to the
377      * wrapped object.
378      */

379     public Object JavaDoc instantiate(String JavaDoc className)
380     throws ReflectionException JavaDoc, MBeanException JavaDoc {
381     checkWrite();
382     return getMBeanServer().instantiate(className);
383     }
384
385     /**
386      * Call <code>checkWrite()</code>, then forward this method to the
387      * wrapped object.
388      */

389     public Object JavaDoc instantiate(String JavaDoc className,
390                   Object JavaDoc params[],
391                   String JavaDoc signature[])
392     throws ReflectionException JavaDoc, MBeanException JavaDoc {
393     checkWrite();
394     return getMBeanServer().instantiate(className, params, signature);
395     }
396
397     /**
398      * Call <code>checkWrite()</code>, then forward this method to the
399      * wrapped object.
400      */

401     public Object JavaDoc instantiate(String JavaDoc className, ObjectName JavaDoc loaderName)
402     throws ReflectionException JavaDoc, MBeanException JavaDoc, InstanceNotFoundException JavaDoc {
403     checkWrite();
404     return getMBeanServer().instantiate(className, loaderName);
405     }
406
407     /**
408      * Call <code>checkWrite()</code>, then forward this method to the
409      * wrapped object.
410      */

411     public Object JavaDoc instantiate(String JavaDoc className, ObjectName JavaDoc loaderName,
412                   Object JavaDoc params[], String JavaDoc signature[])
413     throws ReflectionException JavaDoc, MBeanException JavaDoc, InstanceNotFoundException JavaDoc {
414     checkWrite();
415     return getMBeanServer().instantiate(className, loaderName,
416                         params, signature);
417     }
418
419     /**
420      * Call <code>checkWrite()</code>, then forward this method to the
421      * wrapped object.
422      */

423     public Object JavaDoc invoke(ObjectName JavaDoc name, String JavaDoc operationName,
424              Object JavaDoc params[], String JavaDoc signature[])
425     throws
426     InstanceNotFoundException JavaDoc,
427     MBeanException JavaDoc,
428     ReflectionException JavaDoc {
429     checkWrite();
430         checkMLetMethods(name, operationName);
431     return getMBeanServer().invoke(name, operationName, params, signature);
432     }
433
434     /**
435      * Call <code>checkRead()</code>, then forward this method to the
436      * wrapped object.
437      */

438     public boolean isInstanceOf(ObjectName JavaDoc name, String JavaDoc className)
439     throws InstanceNotFoundException JavaDoc {
440     checkRead();
441     return getMBeanServer().isInstanceOf(name, className);
442     }
443
444     /**
445      * Call <code>checkRead()</code>, then forward this method to the
446      * wrapped object.
447      */

448     public boolean isRegistered(ObjectName JavaDoc name) {
449     checkRead();
450     return getMBeanServer().isRegistered(name);
451     }
452
453     /**
454      * Call <code>checkRead()</code>, then forward this method to the
455      * wrapped object.
456      */

457     public Set JavaDoc queryMBeans(ObjectName JavaDoc name, QueryExp JavaDoc query) {
458     checkRead();
459     return getMBeanServer().queryMBeans(name, query);
460     }
461
462     /**
463      * Call <code>checkRead()</code>, then forward this method to the
464      * wrapped object.
465      */

466     public Set JavaDoc queryNames(ObjectName JavaDoc name, QueryExp JavaDoc query) {
467     checkRead();
468     return getMBeanServer().queryNames(name, query);
469     }
470
471     /**
472      * Call <code>checkWrite()</code>, then forward this method to the
473      * wrapped object.
474      */

475     public ObjectInstance JavaDoc registerMBean(Object JavaDoc object, ObjectName JavaDoc name)
476     throws
477     InstanceAlreadyExistsException JavaDoc,
478     MBeanRegistrationException JavaDoc,
479     NotCompliantMBeanException JavaDoc {
480     checkWrite();
481     return getMBeanServer().registerMBean(object, name);
482     }
483
484     /**
485      * Call <code>checkRead()</code>, then forward this method to the
486      * wrapped object.
487      */

488     public void removeNotificationListener(ObjectName JavaDoc name,
489                        NotificationListener JavaDoc listener)
490     throws InstanceNotFoundException JavaDoc, ListenerNotFoundException JavaDoc {
491     checkRead();
492     getMBeanServer().removeNotificationListener(name, listener);
493     }
494
495     /**
496      * Call <code>checkRead()</code>, then forward this method to the
497      * wrapped object.
498      */

499     public void removeNotificationListener(ObjectName JavaDoc name,
500                        NotificationListener JavaDoc listener,
501                        NotificationFilter JavaDoc filter,
502                        Object JavaDoc handback)
503     throws InstanceNotFoundException JavaDoc, ListenerNotFoundException JavaDoc {
504     checkRead();
505     getMBeanServer().removeNotificationListener(name, listener,
506                             filter, handback);
507     }
508
509     /**
510      * Call <code>checkRead()</code>, then forward this method to the
511      * wrapped object.
512      */

513     public void removeNotificationListener(ObjectName JavaDoc name,
514                        ObjectName JavaDoc listener)
515     throws InstanceNotFoundException JavaDoc, ListenerNotFoundException JavaDoc {
516     checkRead();
517     getMBeanServer().removeNotificationListener(name, listener);
518     }
519
520     /**
521      * Call <code>checkRead()</code>, then forward this method to the
522      * wrapped object.
523      */

524     public void removeNotificationListener(ObjectName JavaDoc name,
525                        ObjectName JavaDoc listener,
526                        NotificationFilter JavaDoc filter,
527                        Object JavaDoc handback)
528     throws InstanceNotFoundException JavaDoc, ListenerNotFoundException JavaDoc {
529     checkRead();
530     getMBeanServer().removeNotificationListener(name, listener,
531                             filter, handback);
532     }
533
534     /**
535      * Call <code>checkWrite()</code>, then forward this method to the
536      * wrapped object.
537      */

538     public void setAttribute(ObjectName JavaDoc name, Attribute JavaDoc attribute)
539     throws
540     InstanceNotFoundException JavaDoc,
541     AttributeNotFoundException JavaDoc,
542     InvalidAttributeValueException JavaDoc,
543     MBeanException JavaDoc,
544     ReflectionException JavaDoc {
545     checkWrite();
546     getMBeanServer().setAttribute(name, attribute);
547     }
548
549     /**
550      * Call <code>checkWrite()</code>, then forward this method to the
551      * wrapped object.
552      */

553     public AttributeList JavaDoc setAttributes(ObjectName JavaDoc name,
554                        AttributeList JavaDoc attributes)
555     throws InstanceNotFoundException JavaDoc, ReflectionException JavaDoc {
556     checkWrite();
557     return getMBeanServer().setAttributes(name, attributes);
558     }
559
560     /**
561      * Call <code>checkWrite()</code>, then forward this method to the
562      * wrapped object.
563      */

564     public void unregisterMBean(ObjectName JavaDoc name)
565     throws InstanceNotFoundException JavaDoc, MBeanRegistrationException JavaDoc {
566     checkWrite();
567     getMBeanServer().unregisterMBean(name);
568     }
569
570     //----------------
571
// PRIVATE METHODS
572
//----------------
573

574     private void checkClassLoader(Object JavaDoc object) {
575     if (object instanceof ClassLoader JavaDoc)
576         throw new SecurityException JavaDoc("Access denied! Creating an " +
577                     "MBean that is a ClassLoader " +
578                     "is forbidden unless a security " +
579                     "manager is installed.");
580     }
581
582     private void checkMLetMethods(ObjectName JavaDoc name, String JavaDoc operation)
583     throws InstanceNotFoundException JavaDoc {
584         // Check if security manager installed
585
SecurityManager JavaDoc sm = System.getSecurityManager();
586         if (sm != null) {
587             return;
588         }
589         // Check for addURL and getMBeansFromURL methods
590
if (!operation.equals("addURL") &&
591                 !operation.equals("getMBeansFromURL")) {
592             return;
593         }
594         // Check if MBean is instance of MLet
595
if (!getMBeanServer().isInstanceOf(name,
596                 "javax.management.loading.MLet")) {
597             return;
598         }
599         // Throw security exception
600
if (operation.equals("addURL")) { // addURL
601
throw new SecurityException JavaDoc("Access denied! MLet method addURL " +
602                     "cannot be invoked unless a security manager is installed.");
603         } else { // getMBeansFromURL
604
// Whether or not calling getMBeansFromURL is allowed is controlled
605
// by the value of the "jmx.remote.x.mlet.allow.getMBeansFromURL"
606
// system property. If the value of this property is true, calling
607
// the MLet's getMBeansFromURL method is allowed. The default value
608
// for this property is false.
609
final String JavaDoc propName = "jmx.remote.x.mlet.allow.getMBeansFromURL";
610             GetPropertyAction propAction = new GetPropertyAction(propName);
611             String JavaDoc propValue = (String JavaDoc) AccessController.doPrivileged(propAction);
612             boolean allowGetMBeansFromURL = "true".equalsIgnoreCase(propValue);
613             if (!allowGetMBeansFromURL) {
614                 throw new SecurityException JavaDoc("Access denied! MLet method " +
615                         "getMBeansFromURL cannot be invoked unless a " +
616                         "security manager is installed or the system property " +
617                         "-Djmx.remote.x.mlet.allow.getMBeansFromURL=true " +
618                         "is specified.");
619             }
620         }
621     }
622
623     //------------------
624
// PRIVATE VARIABLES
625
//------------------
626

627     private MBeanServer JavaDoc mbs;
628 }
629
Popular Tags