diff options
| author | Aidan Skinner <aidan@apache.org> | 2009-01-07 13:32:59 +0000 |
|---|---|---|
| committer | Aidan Skinner <aidan@apache.org> | 2009-01-07 13:32:59 +0000 |
| commit | 400cf393e1a7758d7e08093fcb62bfbd1e8881a3 (patch) | |
| tree | f52957f2f9ffc306c2d41b59a0edaec675168f1d /qpid/java/management/common | |
| parent | de26a37fe587e9ddd8814c0fb9193617daf5dbc5 (diff) | |
| download | qpid-python-400cf393e1a7758d7e08093fcb62bfbd1e8881a3.tar.gz | |
QPID-1539: add management/common module. Move SASL and login code there.
Make gui depend on management common and OSGify it a bit.
git-svn-id: https://svn.apache.org/repos/asf/qpid/trunk@732330 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'qpid/java/management/common')
9 files changed, 647 insertions, 0 deletions
diff --git a/qpid/java/management/common/build.xml b/qpid/java/management/common/build.xml new file mode 100644 index 0000000000..a30aa36578 --- /dev/null +++ b/qpid/java/management/common/build.xml @@ -0,0 +1,25 @@ +<!-- + - + - 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. + - + --> +<project name="Management Common" default="build"> + + <import file="../../module.xml"/> + +</project> diff --git a/qpid/java/management/common/src/main/java/org/apache/qpid/management/common/sasl/CRAMMD5HashedSaslClientFactory.java b/qpid/java/management/common/src/main/java/org/apache/qpid/management/common/sasl/CRAMMD5HashedSaslClientFactory.java new file mode 100644 index 0000000000..be4897d6c4 --- /dev/null +++ b/qpid/java/management/common/src/main/java/org/apache/qpid/management/common/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.common.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/qpid/java/management/common/src/main/java/org/apache/qpid/management/common/sasl/ClientSaslFactory.java b/qpid/java/management/common/src/main/java/org/apache/qpid/management/common/sasl/ClientSaslFactory.java new file mode 100644 index 0000000000..ee5803a220 --- /dev/null +++ b/qpid/java/management/common/src/main/java/org/apache/qpid/management/common/sasl/ClientSaslFactory.java @@ -0,0 +1,54 @@ +/* + * + * 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.common.sasl; + +import java.util.Map; + +import javax.security.auth.callback.CallbackHandler; +import javax.security.sasl.SaslClient; +import javax.security.sasl.SaslClientFactory; +import javax.security.sasl.SaslException; + +public class ClientSaslFactory implements SaslClientFactory +{ + public SaslClient createSaslClient(String[] mechs, String authorizationId, String protocol, + String serverName, Map props, CallbackHandler cbh) + throws SaslException + { + for (int i = 0; i < mechs.length; i++) + { + if (mechs[i].equals("PLAIN")) + { + return new PlainSaslClient(authorizationId, cbh); + } + } + return null; + } + + /** + * Simple-minded implementation that ignores props + */ + public String[] getMechanismNames(Map props) + { + return new String[]{"PLAIN"}; + } + +} diff --git a/qpid/java/management/common/src/main/java/org/apache/qpid/management/common/sasl/Constants.java b/qpid/java/management/common/src/main/java/org/apache/qpid/management/common/sasl/Constants.java new file mode 100644 index 0000000000..31010baf8b --- /dev/null +++ b/qpid/java/management/common/src/main/java/org/apache/qpid/management/common/sasl/Constants.java @@ -0,0 +1,33 @@ +/* + * + * 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.common.sasl; + +public class Constants +{ + + 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/qpid/java/management/common/src/main/java/org/apache/qpid/management/common/sasl/JCAProvider.java b/qpid/java/management/common/src/main/java/org/apache/qpid/management/common/sasl/JCAProvider.java new file mode 100644 index 0000000000..f5a3ca8ccc --- /dev/null +++ b/qpid/java/management/common/src/main/java/org/apache/qpid/management/common/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.common.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/qpid/java/management/common/src/main/java/org/apache/qpid/management/common/sasl/PlainSaslClient.java b/qpid/java/management/common/src/main/java/org/apache/qpid/management/common/sasl/PlainSaslClient.java new file mode 100644 index 0000000000..806975c32f --- /dev/null +++ b/qpid/java/management/common/src/main/java/org/apache/qpid/management/common/sasl/PlainSaslClient.java @@ -0,0 +1,203 @@ +/* + * + * 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.common.sasl; + +import java.io.*; +import javax.security.auth.callback.*; +import javax.security.sasl.*; + +public class PlainSaslClient implements SaslClient +{ + + private boolean completed; + private CallbackHandler cbh; + private String authorizationID; + private String authenticationID; + private byte password[]; + private static byte SEPARATOR = 0; + + public PlainSaslClient(String authorizationID, CallbackHandler cbh) throws SaslException + { + completed = false; + this.cbh = cbh; + Object[] userInfo = getUserInfo(); + this.authorizationID = authorizationID; + this.authenticationID = (String) userInfo[0]; + this.password = (byte[]) userInfo[1]; + if (authenticationID == null || password == null) + { + throw new SaslException("PLAIN: authenticationID and password must be specified"); + } + } + + public byte[] evaluateChallenge(byte[] challenge) throws SaslException + { + if (completed) + { + throw new IllegalStateException("PLAIN: authentication already " + + "completed"); + } + completed = true; + try + { + byte authzid[] = + authorizationID == null ? null : authorizationID.getBytes("UTF8"); + byte authnid[] = authenticationID.getBytes("UTF8"); + byte response[] = + new byte[ + password.length + + authnid.length + + 2 + // SEPARATOR + (authzid != null ? authzid.length : 0) + ]; + int size = 0; + if (authzid != null) { + System.arraycopy(authzid, 0, response, 0, authzid.length); + size = authzid.length; + } + response[size++] = SEPARATOR; + System.arraycopy(authnid, 0, response, size, authnid.length); + size += authnid.length; + response[size++] = SEPARATOR; + System.arraycopy(password, 0, response, size, password.length); + clearPassword(); + return response; + } catch (UnsupportedEncodingException e) { + throw new SaslException("PLAIN: Cannot get UTF-8 encoding of ids", + e); + } + } + + public String getMechanismName() + { + return "PLAIN"; + } + + public boolean hasInitialResponse() + { + return true; + } + + public boolean isComplete() + { + return completed; + } + + public byte[] unwrap(byte[] incoming, int offset, int len) throws SaslException + { + if (completed) { + throw new IllegalStateException("PLAIN: this mechanism supports " + + "neither integrity nor privacy"); + } else { + throw new IllegalStateException("PLAIN: authentication not " + + "completed"); + } + } + + public byte[] wrap(byte[] outgoing, int offset, int len) throws SaslException + { + if (completed) + { + throw new IllegalStateException("PLAIN: this mechanism supports " + + "neither integrity nor privacy"); + } + else + { + throw new IllegalStateException("PLAIN: authentication not " + + "completed"); + } + } + + public Object getNegotiatedProperty(String propName) + { + if (completed) + { + if (propName.equals(Sasl.QOP)) + { + return "auth"; + } + else + { + return null; + } + } + else + { + throw new IllegalStateException("PLAIN: authentication not " + + "completed"); + } + } + + private void clearPassword() + { + if (password != null) + { + for (int i = 0 ; i < password.length ; i++) + { + password[i] = 0; + } + password = null; + } + } + + public void dispose() throws SaslException + { + clearPassword(); + } + + protected void finalize() + { + clearPassword(); + } + + private Object[] getUserInfo() throws SaslException + { + try + { + final String userPrompt = "PLAIN authentication id: "; + final String pwPrompt = "PLAIN password: "; + NameCallback nameCb = new NameCallback(userPrompt); + PasswordCallback passwordCb = new PasswordCallback(pwPrompt, false); + cbh.handle(new Callback[] { nameCb, passwordCb }); + String userid = nameCb.getName(); + char pwchars[] = passwordCb.getPassword(); + byte pwbytes[]; + if (pwchars != null) + { + pwbytes = (new String(pwchars)).getBytes("UTF8"); + passwordCb.clearPassword(); + } + else + { + pwbytes = null; + } + return (new Object[] { userid, pwbytes }); + } + catch (IOException e) + { + throw new SaslException("Cannot get password", e); + } + catch (UnsupportedCallbackException e) + { + throw new SaslException("Cannot get userid/password", e); + } + } +} diff --git a/qpid/java/management/common/src/main/java/org/apache/qpid/management/common/sasl/SaslProvider.java b/qpid/java/management/common/src/main/java/org/apache/qpid/management/common/sasl/SaslProvider.java new file mode 100644 index 0000000000..1eb44e35df --- /dev/null +++ b/qpid/java/management/common/src/main/java/org/apache/qpid/management/common/sasl/SaslProvider.java @@ -0,0 +1,35 @@ +/* + * + * 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.common.sasl; + +import java.security.Provider; + +public class SaslProvider extends Provider +{ + private static final long serialVersionUID = -6978096016899676466L; + + public SaslProvider() + { + super("SaslClientFactory", 1.0, "SASL PLAIN CLIENT MECHANISM"); + put("SaslClientFactory.PLAIN", "ClientSaslFactory"); + } + +} diff --git a/qpid/java/management/common/src/main/java/org/apache/qpid/management/common/sasl/UserPasswordCallbackHandler.java b/qpid/java/management/common/src/main/java/org/apache/qpid/management/common/sasl/UserPasswordCallbackHandler.java new file mode 100644 index 0000000000..a1634f86d9 --- /dev/null +++ b/qpid/java/management/common/src/main/java/org/apache/qpid/management/common/sasl/UserPasswordCallbackHandler.java @@ -0,0 +1,73 @@ +/* + * 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.common.sasl; + +import java.io.*; +import javax.security.auth.callback.*; + +public class UserPasswordCallbackHandler implements CallbackHandler +{ + private String user; + private char[] pwchars; + + public UserPasswordCallbackHandler(String user, String password) + { + this.user = user; + this.pwchars = password.toCharArray(); + } + + 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 void clearPassword() + { + if (pwchars != null) + { + for (int i = 0 ; i < pwchars.length ; i++) + { + pwchars[i] = 0; + } + pwchars = null; + } + } + + protected void finalize() + { + clearPassword(); + } +} diff --git a/qpid/java/management/common/src/main/java/org/apache/qpid/management/common/sasl/UsernameHashedPasswordCallbackHandler.java b/qpid/java/management/common/src/main/java/org/apache/qpid/management/common/sasl/UsernameHashedPasswordCallbackHandler.java new file mode 100644 index 0000000000..09aba1f3e1 --- /dev/null +++ b/qpid/java/management/common/src/main/java/org/apache/qpid/management/common/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.common.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 void clearPassword() + { + if (pwchars != null) + { + for (int i = 0 ; i < pwchars.length ; i++) + { + pwchars[i] = 0; + } + pwchars = null; + } + } + + protected void finalize() + { + clearPassword(); + } + + public static 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 ]; + + int index = 0; + for (byte b : digest) + { + hash[index++] = (char) b; + } + + return hash; + } +} |
