--- a/jdk/src/share/classes/com/sun/jmx/namespace/HandlerInterceptor.java Fri Sep 12 15:17:52 2008 +0200
+++ b/jdk/src/share/classes/com/sun/jmx/namespace/HandlerInterceptor.java Fri Sep 12 17:58:15 2008 +0200
@@ -135,7 +135,11 @@
public AttributeList getAttributes(ObjectName name, String[] attributes)
throws InstanceNotFoundException, ReflectionException {
try {
- return super.getAttributes(name, attributes);
+ final String[] authorized =
+ checkAttributes(name,attributes,"getAttribute");
+ final AttributeList attrList =
+ super.getAttributes(name,authorized);
+ return attrList;
} catch (IOException ex) {
throw handleIOException(ex,"getAttributes",name,attributes);
}
@@ -185,7 +189,8 @@
public void removeNotificationListener(ObjectName name, ObjectName listener)
throws InstanceNotFoundException, ListenerNotFoundException {
try {
- super.removeNotificationListener(name, listener);
+ check(name,null,"removeNotificationListener");
+ super.removeNotificationListener(name,listener);
} catch (IOException ex) {
throw handleIOException(ex,"removeNotificationListener",name,listener);
}
@@ -205,7 +210,9 @@
@Override
public String[] getDomains() {
try {
- return super.getDomains();
+ check(null,null,"getDomains");
+ final String[] domains = super.getDomains();
+ return checkDomains(domains,"getDomains");
} catch (IOException ex) {
throw handleIOException(ex,"getDomains");
}
@@ -228,7 +235,10 @@
InvalidAttributeValueException, MBeanException,
ReflectionException {
try {
- super.setAttribute(name, attribute);
+ check(name,
+ (attribute==null?null:attribute.getName()),
+ "setAttribute");
+ super.setAttribute(name,attribute);
} catch (IOException ex) {
throw handleIOException(ex,"setAttribute",name, attribute);
}
@@ -237,8 +247,10 @@
// From MBeanServerConnection: catch & handles IOException
@Override
public Set<ObjectName> queryNames(ObjectName name, QueryExp query) {
+ if (name == null) name=ObjectName.WILDCARD;
try {
- return super.queryNames(name, query);
+ checkPattern(name,null,"queryNames");
+ return super.queryNames(name,query);
} catch (IOException ex) {
throw handleIOException(ex,"queryNames",name, query);
}
@@ -247,8 +259,10 @@
// From MBeanServerConnection: catch & handles IOException
@Override
public Set<ObjectInstance> queryMBeans(ObjectName name, QueryExp query) {
+ if (name == null) name=ObjectName.WILDCARD;
try {
- return super.queryMBeans(name, query);
+ checkPattern(name,null,"queryMBeans");
+ return super.queryMBeans(name,query);
} catch (IOException ex) {
throw handleIOException(ex,"queryMBeans",name, query);
}
@@ -259,6 +273,7 @@
public boolean isInstanceOf(ObjectName name, String className)
throws InstanceNotFoundException {
try {
+ check(name, null, "isInstanceOf");
return super.isInstanceOf(name, className);
} catch (IOException ex) {
throw handleIOException(ex,"isInstanceOf",name, className);
@@ -272,6 +287,8 @@
MBeanRegistrationException, MBeanException,
NotCompliantMBeanException {
try {
+ checkCreate(name, className, "instantiate");
+ checkCreate(name, className, "registerMBean");
return super.createMBean(className, name);
} catch (IOException ex) {
throw handleIOException(ex,"createMBean",className, name);
@@ -286,6 +303,8 @@
MBeanRegistrationException, MBeanException,
NotCompliantMBeanException, InstanceNotFoundException {
try {
+ checkCreate(name, className, "instantiate");
+ checkCreate(name, className, "registerMBean");
return super.createMBean(className, name, loaderName);
} catch (IOException ex) {
throw handleIOException(ex,"createMBean",className, name, loaderName);
@@ -298,6 +317,7 @@
throws MBeanException, AttributeNotFoundException,
InstanceNotFoundException, ReflectionException {
try {
+ check(name, attribute, "getAttribute");
return super.getAttribute(name, attribute);
} catch (IOException ex) {
throw handleIOException(ex,"getAttribute",name, attribute);
@@ -310,6 +330,7 @@
NotificationFilter filter, Object handback)
throws InstanceNotFoundException, ListenerNotFoundException {
try {
+ check(name,null,"removeNotificationListener");
super.removeNotificationListener(name, listener, filter, handback);
} catch (IOException ex) {
throw handleIOException(ex,"removeNotificationListener",name,
@@ -324,6 +345,7 @@
Object handback)
throws InstanceNotFoundException, ListenerNotFoundException {
try {
+ check(name,null,"removeNotificationListener");
super.removeNotificationListener(name, listener, filter, handback);
} catch (IOException ex) {
throw handleIOException(ex,"removeNotificationListener",name,
@@ -337,6 +359,7 @@
NotificationListener listener)
throws InstanceNotFoundException, ListenerNotFoundException {
try {
+ check(name,null,"removeNotificationListener");
super.removeNotificationListener(name, listener);
} catch (IOException ex) {
throw handleIOException(ex,"removeNotificationListener",name,
@@ -350,6 +373,7 @@
NotificationListener listener, NotificationFilter filter,
Object handback) throws InstanceNotFoundException {
try {
+ check(name,null,"addNotificationListener");
super.addNotificationListener(name, listener, filter, handback);
} catch (IOException ex) {
throw handleIOException(ex,"addNotificationListener",name,
@@ -363,6 +387,7 @@
NotificationFilter filter, Object handback)
throws InstanceNotFoundException {
try {
+ check(name,null,"addNotificationListener");
super.addNotificationListener(name, listener, filter, handback);
} catch (IOException ex) {
throw handleIOException(ex,"addNotificationListener",name,
@@ -385,6 +410,7 @@
public void unregisterMBean(ObjectName name)
throws InstanceNotFoundException, MBeanRegistrationException {
try {
+ check(name, null, "unregisterMBean");
super.unregisterMBean(name);
} catch (IOException ex) {
throw handleIOException(ex,"unregisterMBean",name);
@@ -397,6 +423,7 @@
throws InstanceNotFoundException, IntrospectionException,
ReflectionException {
try {
+ check(name, null, "getMBeanInfo");
return super.getMBeanInfo(name);
} catch (IOException ex) {
throw handleIOException(ex,"getMBeanInfo",name);
@@ -408,6 +435,7 @@
public ObjectInstance getObjectInstance(ObjectName name)
throws InstanceNotFoundException {
try {
+ check(name, null, "getObjectInstance");
return super.getObjectInstance(name);
} catch (IOException ex) {
throw handleIOException(ex,"getObjectInstance",name);
@@ -422,6 +450,8 @@
MBeanRegistrationException, MBeanException,
NotCompliantMBeanException {
try {
+ checkCreate(name, className, "instantiate");
+ checkCreate(name, className, "registerMBean");
return super.createMBean(className, name, params, signature);
} catch (IOException ex) {
throw handleIOException(ex,"createMBean",className, name,
@@ -437,6 +467,8 @@
MBeanRegistrationException, MBeanException,
NotCompliantMBeanException, InstanceNotFoundException {
try {
+ checkCreate(name, className, "instantiate");
+ checkCreate(name, className, "registerMBean");
return super.createMBean(className, name, loaderName, params,
signature);
} catch (IOException ex) {
@@ -450,7 +482,9 @@
public AttributeList setAttributes(ObjectName name,AttributeList attributes)
throws InstanceNotFoundException, ReflectionException {
try {
- return super.setAttributes(name, attributes);
+ final AttributeList authorized =
+ checkAttributes(name, attributes, "setAttribute");
+ return super.setAttributes(name, authorized);
} catch (IOException ex) {
throw handleIOException(ex,"setAttributes",name, attributes);
}
@@ -462,6 +496,7 @@
String[] signature)
throws InstanceNotFoundException, MBeanException, ReflectionException {
try {
+ check(name, operationName, "invoke");
return super.invoke(name, operationName, params, signature);
} catch (IOException ex) {
throw handleIOException(ex,"invoke",name, operationName,
@@ -582,4 +617,118 @@
"Not supported in this namespace: "+namespace));
}
+ /**
+ * A result might be excluded for security reasons.
+ */
+ @Override
+ boolean excludesFromResult(ObjectName targetName, String queryMethod) {
+ return !checkQuery(targetName, queryMethod);
+ }
+
+
+ //----------------------------------------------------------------------
+ // Hooks for checking permissions
+ //----------------------------------------------------------------------
+
+ /**
+ * This method is a hook to implement permission checking in subclasses.
+ * A subclass may override this method and throw a {@link
+ * SecurityException} if the permission is denied.
+ *
+ * @param routingName The name of the MBean in the enclosing context.
+ * This is of the form {@code <namespace>//<ObjectName>}.
+ * @param member The {@link
+ * javax.management.namespace.JMXNamespacePermission#getMember member}
+ * name.
+ * @param action The {@link
+ * javax.management.namespace.JMXNamespacePermission#getActions action}
+ * name.
+ * @throws SecurityException if the caller doesn't have the permission
+ * to perform the given action on the MBean pointed to
+ * by routingName.
+ */
+ abstract void check(ObjectName routingName,
+ String member, String action);
+
+ // called in createMBean and registerMBean
+ abstract void checkCreate(ObjectName routingName, String className,
+ String action);
+
+ /**
+ * This is a hook to implement permission checking in subclasses.
+ *
+ * Checks that the caller has sufficient permission for returning
+ * information about {@code sourceName} in {@code action}.
+ *
+ * Subclass may override this method and return false if the caller
+ * doesn't have sufficient permissions.
+ *
+ * @param routingName The name of the MBean to include or exclude from
+ * the query, expressed in the enclosing context.
+ * This is of the form {@code <namespace>//<ObjectName>}.
+ * @param action one of "queryNames" or "queryMBeans"
+ * @return true if {@code sourceName} can be returned.
+ */
+ abstract boolean checkQuery(ObjectName routingName, String action);
+
+ /**
+ * This method is a hook to implement permission checking in subclasses.
+ *
+ * @param routingName The name of the MBean in the enclosing context.
+ * This is of the form {@code <namespace>//<ObjectName>}.
+ * @param attributes The list of attributes to check permission for.
+ * @param action one of "getAttribute" or "setAttribute"
+ * @return The list of attributes for which the callers has the
+ * appropriate {@link
+ * javax.management.namespace.JMXNamespacePermission}.
+ * @throws SecurityException if the caller doesn't have the permission
+ * to perform {@code action} on the MBean pointed to by routingName.
+ */
+ abstract String[] checkAttributes(ObjectName routingName,
+ String[] attributes, String action);
+
+ /**
+ * This method is a hook to implement permission checking in subclasses.
+ *
+ * @param routingName The name of the MBean in the enclosing context.
+ * This is of the form {@code <namespace>//<ObjectName>}.
+ * @param attributes The list of attributes to check permission for.
+ * @param action one of "getAttribute" or "setAttribute"
+ * @return The list of attributes for which the callers has the
+ * appropriate {@link
+ * javax.management.namespace.JMXNamespacePermission}.
+ * @throws SecurityException if the caller doesn't have the permission
+ * to perform {@code action} on the MBean pointed to by routingName.
+ */
+ abstract AttributeList checkAttributes(ObjectName routingName,
+ AttributeList attributes, String action);
+
+ /**
+ * This method is a hook to implement permission checking in subclasses.
+ * Checks that the caller as the necessary permissions to view the
+ * given domain. If not remove the domains for which the caller doesn't
+ * have permission from the list.
+ * <p>
+ * By default, this method always returns {@code domains}
+ *
+ * @param domains The domains to return.
+ * @param action "getDomains"
+ * @return a filtered list of domains.
+ */
+ String[] checkDomains(String[] domains, String action) {
+ return domains;
+ }
+
+ // A priori check for queryNames/queryMBeans/
+ void checkPattern(ObjectName routingPattern,
+ String member, String action) {
+ // pattern is checked only at posteriori by checkQuery.
+ // checking it a priori usually doesn't work, because ObjectName.apply
+ // does not work between two patterns.
+ // We only check that we have the permission requested for 'action'.
+ check(null,null,action);
+ }
+
+
+
}
--- a/jdk/src/share/classes/com/sun/jmx/namespace/RoutingMBeanServerConnection.java Fri Sep 12 15:17:52 2008 +0200
+++ b/jdk/src/share/classes/com/sun/jmx/namespace/RoutingMBeanServerConnection.java Fri Sep 12 17:58:15 2008 +0200
@@ -161,11 +161,7 @@
throws InstanceNotFoundException, ReflectionException, IOException {
final ObjectName sourceName = toSourceOrRuntime(name);
try {
- final String[] authorized =
- checkAttributes(name,attributes,"getAttribute");
- final AttributeList attrList =
- source().getAttributes(sourceName,authorized);
- return attrList;
+ return source().getAttributes(sourceName, attributes);
} catch (RuntimeException ex) {
throw makeCompliantRuntimeException(ex);
}
@@ -178,7 +174,6 @@
IOException {
final ObjectName sourceName = toSourceOrRuntime(name);
try {
- check(name, operationName, "invoke");
final Object result =
source().invoke(sourceName,operationName,params,
signature);
@@ -194,7 +189,6 @@
IOException {
final ObjectName sourceName = toSourceOrRuntime(name);
try {
- check(name, null, "unregisterMBean");
source().unregisterMBean(sourceName);
} catch (RuntimeException ex) {
throw makeCompliantRuntimeException(ex);
@@ -207,7 +201,6 @@
ReflectionException, IOException {
final ObjectName sourceName = toSourceOrRuntime(name);
try {
- check(name, null, "getMBeanInfo");
return source().getMBeanInfo(sourceName);
} catch (RuntimeException ex) {
throw makeCompliantRuntimeException(ex);
@@ -219,7 +212,6 @@
throws InstanceNotFoundException, IOException {
final ObjectName sourceName = toSourceOrRuntime(name);
try {
- check(name, null, "getObjectInstance");
return processOutputInstance(
source().getObjectInstance(sourceName));
} catch (RuntimeException ex) {
@@ -246,9 +238,6 @@
ReflectionException, IOException {
final ObjectName sourceName = toSourceOrRuntime(name);
try {
- check(name,
- (attribute==null?null:attribute.getName()),
- "setAttribute");
source().setAttribute(sourceName,attribute);
} catch (RuntimeException ex) {
throw makeCompliantRuntimeException(ex);
@@ -266,8 +255,6 @@
// Loader Name is already a sourceLoaderName.
final ObjectName sourceLoaderName = loaderName;
try {
- checkCreate(name, className, "instantiate");
- checkCreate(name, className, "registerMBean");
final ObjectInstance instance =
source().createMBean(className,sourceName,
sourceLoaderName,
@@ -286,8 +273,6 @@
NotCompliantMBeanException, IOException {
final ObjectName sourceName = newSourceMBeanName(name);
try {
- checkCreate(name, className, "instantiate");
- checkCreate(name, className, "registerMBean");
return processOutputInstance(source().createMBean(className,
sourceName,params,signature));
} catch (RuntimeException ex) {
@@ -305,8 +290,6 @@
// Loader Name is already a source Loader Name.
final ObjectName sourceLoaderName = loaderName;
try {
- checkCreate(name, className, "instantiate");
- checkCreate(name, className, "registerMBean");
return processOutputInstance(source().createMBean(className,
sourceName,sourceLoaderName));
} catch (RuntimeException ex) {
@@ -321,8 +304,6 @@
NotCompliantMBeanException, IOException {
final ObjectName sourceName = newSourceMBeanName(name);
try {
- checkCreate(name, className, "instantiate");
- checkCreate(name, className, "registerMBean");
return processOutputInstance(source().
createMBean(className,sourceName));
} catch (RuntimeException ex) {
@@ -336,7 +317,6 @@
InstanceNotFoundException, ReflectionException, IOException {
final ObjectName sourceName = toSourceOrRuntime(name);
try {
- check(name, attribute, "getAttribute");
return source().getAttribute(sourceName,attribute);
} catch (RuntimeException ex) {
throw makeCompliantRuntimeException(ex);
@@ -348,7 +328,6 @@
throws InstanceNotFoundException, IOException {
final ObjectName sourceName = toSourceOrRuntime(name);
try {
- check(name, null, "isInstanceOf");
return source().isInstanceOf(sourceName,className);
} catch (RuntimeException ex) {
throw makeCompliantRuntimeException(ex);
@@ -360,10 +339,8 @@
throws InstanceNotFoundException, ReflectionException, IOException {
final ObjectName sourceName = toSourceOrRuntime(name);
try {
- final AttributeList authorized =
- checkAttributes(name, attributes, "setAttribute");
return source().
- setAttributes(sourceName,authorized);
+ setAttributes(sourceName,attributes);
} catch (RuntimeException ex) {
throw makeCompliantRuntimeException(ex);
}
@@ -376,7 +353,7 @@
for (ObjectInstance i : sources) {
try {
final ObjectInstance target = processOutputInstance(i);
- if (!checkQuery(target.getObjectName(), "queryMBeans"))
+ if (excludesFromResult(target.getObjectName(), "queryMBeans"))
continue;
result.add(target);
} catch (Exception x) {
@@ -415,7 +392,7 @@
for (ObjectName n : sourceNames) {
try {
final ObjectName targetName = toTarget(n);
- if (!checkQuery(targetName, "queryNames")) continue;
+ if (excludesFromResult(targetName, "queryNames")) continue;
names.add(targetName);
} catch (Exception x) {
if (LOG.isLoggable(Level.FINE)) {
@@ -435,7 +412,6 @@
if (name == null) name=ObjectName.WILDCARD;
final ObjectName sourceName = toSourceOrRuntime(name);
try {
- checkPattern(name,null,"queryMBeans");
return processOutputInstances(
source().queryMBeans(sourceName,query));
} catch (RuntimeException ex) {
@@ -450,7 +426,6 @@
if (name == null) name=ObjectName.WILDCARD;
final ObjectName sourceName = toSourceOrRuntime(name);
try {
- checkPattern(name,null,"queryNames");
final Set<ObjectName> tmp = source().queryNames(sourceName,query);
final Set<ObjectName> out = processOutputNames(tmp);
//System.err.println("queryNames: out: "+out);
@@ -467,7 +442,6 @@
ListenerNotFoundException, IOException {
final ObjectName sourceName = toSourceOrRuntime(name);
try {
- check(name,null,"removeNotificationListener");
source().removeNotificationListener(sourceName,listener);
} catch (RuntimeException ex) {
throw makeCompliantRuntimeException(ex);
@@ -481,7 +455,6 @@
final ObjectName sourceName = toSourceOrRuntime(name);
// Listener name is already a source listener name.
try {
- check(name,null,"addNotificationListener");
source().addNotificationListener(sourceName,listener,
filter,handback);
} catch (RuntimeException ex) {
@@ -495,7 +468,6 @@
Object handback) throws InstanceNotFoundException, IOException {
final ObjectName sourceName = toSourceOrRuntime(name);
try {
- check(name,null,"addNotificationListener");
source().addNotificationListener(sourceName, listener, filter,
handback);
} catch (RuntimeException ex) {
@@ -512,7 +484,6 @@
IOException {
final ObjectName sourceName = toSourceOrRuntime(name);
try {
- check(name,null,"removeNotificationListener");
source().removeNotificationListener(sourceName,listener,filter,
handback);
} catch (RuntimeException ex) {
@@ -527,7 +498,6 @@
IOException {
final ObjectName sourceName = toSourceOrRuntime(name);
try {
- check(name,null,"removeNotificationListener");
source().removeNotificationListener(sourceName,listener,
filter,handback);
} catch (RuntimeException ex) {
@@ -543,7 +513,6 @@
// listener name is already a source name...
final ObjectName sourceListener = listener;
try {
- check(name,null,"removeNotificationListener");
source().removeNotificationListener(sourceName,sourceListener);
} catch (RuntimeException ex) {
throw makeCompliantRuntimeException(ex);
@@ -562,9 +531,7 @@
// from MBeanServerConnection
public String[] getDomains() throws IOException {
try {
- check(null,null,"getDomains");
- final String[] domains = source().getDomains();
- return checkDomains(domains,"getDomains");
+ return source().getDomains();
} catch (RuntimeException ex) {
throw makeCompliantRuntimeException(ex);
}
@@ -579,115 +546,22 @@
}
}
- //----------------------------------------------------------------------
- // Hooks for checking permissions
- //----------------------------------------------------------------------
-
/**
- * This method is a hook to implement permission checking in subclasses.
- * By default, this method does nothing and simply returns
- * {@code attribute}.
+ * Returns true if the given targetName must be excluded from the
+ * query result.
+ * In this base class, always return {@code false}.
+ * By default all object names returned by the sources are
+ * transmitted to the caller - there is no filtering.
*
- * @param routingName The name of the MBean in the enclosing context.
- * This is of the form {@code <namespace>//<ObjectName>}.
- * @param attributes The list of attributes to check permission for.
- * @param action one of "getAttribute" or "setAttribute"
- * @return The list of attributes for which the callers has the
- * appropriate {@link
- * javax.management.namespace.JMXNamespacePermission}.
+ * @param name A target object name expressed in the caller's
+ * context. In the case of cascading, where the source
+ * is a sub agent mounted on e.g. namespace "foo",
+ * that would be a name prefixed by "foo//"...
+ * @param queryMethod either "queryNames" or "queryMBeans".
+ * @return true if the name must be excluded.
*/
- String[] checkAttributes(ObjectName routingName,
- String[] attributes, String action) {
- check(routingName,null,action);
- return attributes;
- }
-
- /**
- * This method is a hook to implement permission checking in subclasses.
- * By default, this method does nothing and simply returns
- * {@code attribute}.
- *
- * @param routingName The name of the MBean in the enclosing context.
- * This is of the form {@code <namespace>//<ObjectName>}.
- * @param attributes The list of attributes to check permission for.
- * @param action one of "getAttribute" or "setAttribute"
- * @return The list of attributes for which the callers has the
- * appropriate {@link
- * javax.management.namespace.JMXNamespacePermission}.
- */
- AttributeList checkAttributes(ObjectName routingName,
- AttributeList attributes, String action) {
- check(routingName,null,action);
- return attributes;
+ boolean excludesFromResult(ObjectName targetName, String queryMethod) {
+ return false;
}
- /**
- * This method is a hook to implement permission checking in subclasses.
- * By default, this method does nothing.
- * A subclass may override this method and throw a {@link
- * SecurityException} if the permission is denied.
- *
- * @param routingName The name of the MBean in the enclosing context.
- * This is of the form {@code <namespace>//<ObjectName>}.
- * @param member The {@link
- * javax.management.namespace.JMXNamespacePermission#getMember member}
- * name.
- * @param action The {@link
- * javax.management.namespace.JMXNamespacePermission#getActions action}
- * name.
- */
- void check(ObjectName routingName,
- String member, String action) {
- }
-
- // called in createMBean and registerMBean
- void checkCreate(ObjectName routingName, String className,
- String action) {
- }
-
- // A priori check for queryNames/queryMBeans/
- void checkPattern(ObjectName routingPattern,
- String member, String action) {
- // pattern is checked only at posteriori by checkQuery.
- // checking it a priori usually doesn't work, because ObjectName.apply
- // does not work between two patterns.
- // We only check that we have the permission requested for 'action'.
- check(null,null,action);
- }
-
-
- /**
- * This is a hook to implement permission checking in subclasses.
- *
- * Checks that the caller has sufficient permission for returning
- * information about {@code sourceName} in {@code action}.
- *
- * By default always return true. Subclass may override this method
- * and return false if the caller doesn't have sufficient permissions.
- *
- * @param routingName The name of the MBean to include or exclude from
- * the query, expressed in the enclosing context.
- * This is of the form {@code <namespace>//<ObjectName>}.
- * @param action one of "queryNames" or "queryMBeans"
- * @return true if {@code sourceName} can be returned.
- */
- boolean checkQuery(ObjectName routingName, String action) {
- return true;
- }
-
- /**
- * This method is a hook to implement permission checking in subclasses.
- * Checks that the caller as the necessary permissions to view the
- * given domain. If not remove the domains for which the caller doesn't
- * have permission from the list.
- * <p>
- * By default, this method always returns {@code domains}
- *
- * @param domains The domains to return.
- * @param action "getDomains"
- * @return a filtered list of domains.
- */
- String[] checkDomains(String[] domains, String action) {
- return domains;
- }
}