diff options
| author | Bhupendra Bhusman Bhardwaj <bhupendrab@apache.org> | 2007-04-11 14:16:02 +0000 |
|---|---|---|
| committer | Bhupendra Bhusman Bhardwaj <bhupendrab@apache.org> | 2007-04-11 14:16:02 +0000 |
| commit | 41a95c994d425ea0dcb1ae5a099da1e530eadc87 (patch) | |
| tree | f2d54f1ad81df7e5b79269129c2e66588f2a8418 /java/management/eclipse-plugin/src | |
| parent | b287b96e81dfff14c63285afb8c461187b18f87f (diff) | |
| download | qpid-python-41a95c994d425ea0dcb1ae5a099da1e530eadc87.tar.gz | |
QPID-444 : added CRAM-MD5-HASHED mechanism for sasl
git-svn-id: https://svn.apache.org/repos/asf/incubator/qpid/branches/M2@527499 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'java/management/eclipse-plugin/src')
8 files changed, 283 insertions, 37 deletions
diff --git a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ApplicationRegistry.java b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ApplicationRegistry.java index c15bdc4fa0..714f84ea49 100644 --- a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ApplicationRegistry.java +++ b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ApplicationRegistry.java @@ -41,8 +41,9 @@ public abstract class ApplicationRegistry { private static ImageRegistry imageRegistry = new ImageRegistry(); private static FontRegistry fontRegistry = new FontRegistry(); - public static final boolean enableSecurity = Boolean.getBoolean("security"); - + public static final boolean debug = Boolean.getBoolean("debug"); + public static final String securityMechanism = System.getProperty("security", null); + static { imageRegistry.put(Constants.CONSOLE_IMAGE, @@ -131,4 +132,9 @@ public abstract class ApplicationRegistry _closedServerList.clear(); return list; } + + public static String getSecurityMechanism() + { + return securityMechanism; + } } diff --git a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/Constants.java b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/Constants.java index 91dec841cf..dd3c388ed4 100644 --- a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/Constants.java +++ b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/Constants.java @@ -123,4 +123,9 @@ public class Constants public final static String INFO_HOST_PORT = "Please enter the port number"; public final static String INFO_USERNAME = "Please enter the " + USERNAME; public final static String INFO_PASSWORD = "Please enter the " + PASSWORD; + + public final static String MECH_CRAMMD5 = "CRAM-MD5"; + public final static String MECH_PLAIN = "PLAIN"; + public final static String SASL_CRAMMD5 = "SASL/CRAM-MD5"; + public final static String SASL_PLAIN = "SASL/PLAIN"; } diff --git a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/jmx/ClientListener.java b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/jmx/ClientListener.java index 82447d645e..2be0ddbebf 100644 --- a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/jmx/ClientListener.java +++ b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/jmx/ClientListener.java @@ -45,10 +45,7 @@ public class ClientListener implements NotificationListener { ObjectName objName = null; String type = notification.getType(); - if (MBeanUtility.isDebug()) - { - System.out.println(type + ":" + objName); - } + MBeanUtility.printOutput(type + ":" + objName); if (MBeanServerNotification.REGISTRATION_NOTIFICATION.equals(type)) { diff --git a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/jmx/JMXServerRegistry.java b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/jmx/JMXServerRegistry.java index 435f7f2ff1..4040f544d1 100644 --- a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/jmx/JMXServerRegistry.java +++ b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/jmx/JMXServerRegistry.java @@ -20,6 +20,8 @@ */ package org.apache.qpid.management.ui.jmx; +import static org.apache.qpid.management.ui.Constants.*; + import java.lang.reflect.Constructor; import java.security.Security; import java.util.ArrayList; @@ -37,9 +39,9 @@ import javax.management.ObjectName; import javax.management.remote.JMXConnector; import javax.management.remote.JMXConnectorFactory; import javax.management.remote.JMXServiceURL; +import javax.security.sasl.SaslClientFactory; import org.apache.qpid.management.ui.ApplicationRegistry; -import org.apache.qpid.management.ui.Constants; import org.apache.qpid.management.ui.ManagedBean; import org.apache.qpid.management.ui.ManagedServer; import org.apache.qpid.management.ui.ServerRegistry; @@ -47,8 +49,10 @@ import org.apache.qpid.management.ui.model.ManagedAttributeModel; import org.apache.qpid.management.ui.model.NotificationInfoModel; import org.apache.qpid.management.ui.model.NotificationObject; import org.apache.qpid.management.ui.model.OperationDataModel; +import org.apache.qpid.management.ui.sasl.JCAProvider; import org.apache.qpid.management.ui.sasl.SaslProvider; import org.apache.qpid.management.ui.sasl.UserPasswordCallbackHandler; +import org.apache.qpid.management.ui.sasl.UsernameHashedPasswordCallbackHandler; public class JMXServerRegistry extends ServerRegistry @@ -89,37 +93,58 @@ public class JMXServerRegistry extends ServerRegistry super(server); JMXServiceURL jmxUrl = new JMXServiceURL(server.getUrl()); Map<String, Object> env = null; + String securityMechanism = ApplicationRegistry.getSecurityMechanism(); - if (ApplicationRegistry.enableSecurity) + if (securityMechanism != null) { try { // Check if the JMXMP connector is available Class klass = Class.forName("javax.management.remote.jmxmp.JMXMPConnector"); - // Now create the instance of JMXMPConnector - Security.addProvider(new SaslProvider()); jmxUrl = new JMXServiceURL("jmxmp", server.getHost(), server.getPort()); - env = new HashMap<String, Object>(); - env.put("jmx.remote.profiles", "SASL/PLAIN"); - //env.put("jmx.remote.profiles", "SASL/CRAM-MD5"); - env.put("jmx.remote.sasl.callback.handler", - new UserPasswordCallbackHandler(server.getUser(), server.getPassword())); + if (MECH_CRAMMD5.equals(securityMechanism)) + { + // For SASL/CRAM-MD5 + Map<String, Class<? extends SaslClientFactory>> map = new HashMap<String, Class<? extends SaslClientFactory>>(); + Class<?> clazz = Class.forName("org.apache.qpid.management.ui.sasl.CRAMMD5HashedSaslClientFactory"); + map.put("CRAM-MD5-HASHED", (Class<? extends SaslClientFactory>) clazz); + + Security.addProvider(new JCAProvider(map)); + env.put("jmx.remote.profiles", SASL_CRAMMD5); + env.put("jmx.remote.sasl.callback.handler", + new UsernameHashedPasswordCallbackHandler(server.getUser(), server.getPassword())); + } + else if (MECH_PLAIN.equals(securityMechanism)) + { + // For SASL/PLAIN + Security.addProvider(new SaslProvider()); + env.put("jmx.remote.profiles", SASL_PLAIN); + env.put("jmx.remote.sasl.callback.handler", + new UserPasswordCallbackHandler(server.getUser(), server.getPassword())); + } + else + { + MBeanUtility.printOutput("Security mechanism " + securityMechanism + " is not supported."); + } + + // Now create the instance of JMXMPConnector Class[] paramTypes = {JMXServiceURL.class, Map.class}; Constructor cons = klass.getConstructor(paramTypes); Object[] args = {jmxUrl, env}; Object theObject = cons.newInstance(args); + _jmxc = (JMXConnector)theObject; _jmxc.connect(); - System.out.println("Starting JMXConnector with SASL. Server=" + server.getName()); + MBeanUtility.printOutput("Starting JMXConnector with SASL. Server=" + server.getName()); } catch (Exception ex) { // When JMXMPConnector is not available - System.out.println("Starting JMXConnector. Server=" + server.getName()); + MBeanUtility.printOutput("Starting JMXConnector. Server=" + server.getName()); jmxUrl = new JMXServiceURL(server.getUrl()); _jmxc = JMXConnectorFactory.connect(jmxUrl, null); } @@ -197,10 +222,7 @@ public class JMXServerRegistry extends ServerRegistry public void removeManagedObject(ManagedBean mbean) { - if (MBeanUtility.isDebug()) - { - System.out.println("Removing MBean:" + mbean.getUniqueName()); - } + MBeanUtility.printOutput("Removing MBean:" + mbean.getUniqueName()); if (mbean.isQueue()) { @@ -296,7 +318,7 @@ public class JMXServerRegistry extends ServerRegistry map.put(name, list); } // Now add the notification type to the list - if (Constants.ALL.equals(type)) + if (ALL.equals(type)) { List<NotificationInfoModel> infoList = _notificationInfoMap.get(mbean.getUniqueName()); for (NotificationInfoModel model : infoList) @@ -355,7 +377,7 @@ public class JMXServerRegistry extends ServerRegistry HashMap<String, List<String>> map = _subscribedNotificationMap.get(mbean.getUniqueName()); if (map.containsKey(name)) { - if (Constants.ALL.equals(type)) + if (ALL.equals(type)) { map.remove(name); } diff --git a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/jmx/MBeanUtility.java b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/jmx/MBeanUtility.java index 6c34ec9898..41db11c10e 100644 --- a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/jmx/MBeanUtility.java +++ b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/jmx/MBeanUtility.java @@ -60,13 +60,6 @@ import org.apache.qpid.management.ui.views.ViewUtility; */ public class MBeanUtility { - private static boolean _debug; - static - { - String debug = System.getProperty("debug"); - _debug = "true".equalsIgnoreCase(debug) ? true : false; - } - public static final BigInteger MAX_LONG = BigInteger.valueOf(Long.MAX_VALUE); public static final BigInteger MAX_INT = BigInteger.valueOf(Integer.MAX_VALUE); /** @@ -461,18 +454,17 @@ public class MBeanUtility return Arrays.asList(domains); } - /** - * return true if System property is set to true -Ddebug=true - * @return - */ - public static boolean isDebug() + public static void printOutput(String statement) { - return _debug; + if (ApplicationRegistry.debug) + { + System.out.println(statement); + } } private static void printStackTrace(Throwable ex) { - if (isDebug()) + if (ApplicationRegistry.debug) { ex.printStackTrace(); } diff --git a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/sasl/CRAMMD5HashedSaslClientFactory.java b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/sasl/CRAMMD5HashedSaslClientFactory.java new file mode 100644 index 0000000000..32a0c12344 --- /dev/null +++ b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/sasl/CRAMMD5HashedSaslClientFactory.java @@ -0,0 +1,60 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.ui.sasl; + +import java.util.Map; + +import javax.security.auth.callback.CallbackHandler; +import javax.security.sasl.Sasl; +import javax.security.sasl.SaslClient; +import javax.security.sasl.SaslClientFactory; +import javax.security.sasl.SaslException; + +public class CRAMMD5HashedSaslClientFactory implements SaslClientFactory +{ + /** The name of this mechanism */ + public static final String MECHANISM = "CRAM-MD5-HASHED"; + + public SaslClient createSaslClient(String[] mechanisms, String authorizationId, String protocol, + String serverName, Map<String, ?> props, CallbackHandler cbh) + throws SaslException + { + for (int i = 0; i < mechanisms.length; i++) + { + if (mechanisms[i].equals(MECHANISM)) + { + if (cbh == null) + { + throw new SaslException("CallbackHandler must not be null"); + } + + String[] mechs = {"CRAM-MD5"}; + return Sasl.createSaslClient(mechs, authorizationId, protocol, serverName, props, cbh); + } + } + return null; + } + + public String[] getMechanismNames(Map props) + { + return new String[]{MECHANISM}; + } +} diff --git a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/sasl/JCAProvider.java b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/sasl/JCAProvider.java new file mode 100644 index 0000000000..d8189f3ac3 --- /dev/null +++ b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/sasl/JCAProvider.java @@ -0,0 +1,56 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.ui.sasl; + +import java.security.Provider; +import java.util.Map; + +import javax.security.sasl.SaslClientFactory; + +public class JCAProvider extends Provider +{ + private static final long serialVersionUID = 1L; + + /** + * Creates the security provider with a map from SASL mechanisms to implementing factories. + * + * @param providerMap The map from SASL mechanims to implementing factory classes. + */ + public JCAProvider(Map<String, Class<? extends SaslClientFactory>> providerMap) + { + super("AMQSASLProvider", 1.0, "A JCA provider that registers all " + + "AMQ SASL providers that want to be registered"); + register(providerMap); + } + + /** + * Registers client factory classes for a map of mechanism names to client factory classes. + * + * @param providerMap The map from SASL mechanims to implementing factory classes. + */ + private void register(Map<String, Class<? extends SaslClientFactory>> providerMap) + { + for (Map.Entry<String, Class<? extends SaslClientFactory>> me : providerMap.entrySet()) + { + put("SaslClientFactory." + me.getKey(), me.getValue().getName()); + } + } +} diff --git a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/sasl/UsernameHashedPasswordCallbackHandler.java b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/sasl/UsernameHashedPasswordCallbackHandler.java new file mode 100644 index 0000000000..12090e866a --- /dev/null +++ b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/sasl/UsernameHashedPasswordCallbackHandler.java @@ -0,0 +1,108 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.ui.sasl; + +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; + +import javax.security.auth.callback.Callback; +import javax.security.auth.callback.CallbackHandler; +import javax.security.auth.callback.NameCallback; +import javax.security.auth.callback.PasswordCallback; +import javax.security.auth.callback.UnsupportedCallbackException; + +public class UsernameHashedPasswordCallbackHandler implements CallbackHandler +{ + private String user; + private char[] pwchars; + + public UsernameHashedPasswordCallbackHandler(String user, String password) throws Exception + { + this.user = user; + this.pwchars = getHash(password); + } + + public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException + { + for (int i = 0; i < callbacks.length; i++) + { + if (callbacks[i] instanceof NameCallback) + { + NameCallback ncb = (NameCallback) callbacks[i]; + ncb.setName(user); + } + else if (callbacks[i] instanceof PasswordCallback) + { + PasswordCallback pcb = (PasswordCallback) callbacks[i]; + pcb.setPassword(pwchars); + } + else + { + throw new UnsupportedCallbackException(callbacks[i]); + } + } + } + + private char[] getHash(String text) throws NoSuchAlgorithmException, UnsupportedEncodingException + { + + byte[] data = text.getBytes("utf-8"); + + MessageDigest md = MessageDigest.getInstance("MD5"); + + for (byte b : data) + { + md.update(b); + } + + byte[] digest = md.digest(); + + char[] hash = new char[digest.length + 1]; + + int index = 0; + for (byte b : digest) + { + index++; + hash[index] = (char) b; + } + + return hash; + } + + private void clearPassword() + { + if (pwchars != null) + { + for (int i = 0 ; i < pwchars.length ; i++) + { + pwchars[i] = 0; + } + pwchars = null; + } + } + + protected void finalize() + { + clearPassword(); + } +} |
