You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@qpid.apache.org by ro...@apache.org on 2009/11/27 12:44:54 UTC

svn commit: r884838 - in /qpid/trunk/qpid/java/broker/src: main/java/org/apache/qpid/server/security/auth/database/ main/java/org/apache/qpid/server/security/auth/sasl/crammd5/ test/java/org/apache/qpid/server/securiity/ test/java/org/apache/qpid/serve...

Author: robbie
Date: Fri Nov 27 11:44:54 2009
New Revision: 884838

URL: http://svn.apache.org/viewvc?rev=884838&view=rev
Log:
QPID-2222: Add CRAM-MD5-HEX support to broker to enable .net client to connect to broker when using Base64MD5 password file.

Changes merged from M2.x branch r664001 with update to implement the newer reload() PD method.

Added:
    qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/crammd5/CRAMMD5HexInitialiser.java
    qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/crammd5/CRAMMD5HexSaslServer.java
    qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/crammd5/CRAMMD5HexServerFactory.java
    qpid/trunk/qpid/java/broker/src/test/java/org/apache/qpid/server/securiity/
    qpid/trunk/qpid/java/broker/src/test/java/org/apache/qpid/server/securiity/auth/
    qpid/trunk/qpid/java/broker/src/test/java/org/apache/qpid/server/securiity/auth/sasl/
    qpid/trunk/qpid/java/broker/src/test/java/org/apache/qpid/server/securiity/auth/sasl/CRAMMD5HexInitialiserTest.java
Modified:
    qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/Base64MD5PasswordFilePrincipalDatabase.java

Modified: qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/Base64MD5PasswordFilePrincipalDatabase.java
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/Base64MD5PasswordFilePrincipalDatabase.java?rev=884838&r1=884837&r2=884838&view=diff
==============================================================================
--- qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/Base64MD5PasswordFilePrincipalDatabase.java (original)
+++ qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/Base64MD5PasswordFilePrincipalDatabase.java Fri Nov 27 11:44:54 2009
@@ -24,6 +24,7 @@
 import org.apache.qpid.server.security.access.management.AMQUserManagementMBean;
 import org.apache.qpid.server.security.auth.sasl.AuthenticationProviderInitialiser;
 import org.apache.qpid.server.security.auth.sasl.UsernamePrincipal;
+import org.apache.qpid.server.security.auth.sasl.crammd5.CRAMMD5HexInitialiser;
 import org.apache.qpid.server.security.auth.sasl.crammd5.CRAMMD5HashedInitialiser;
 import org.apache.qpid.util.FileUtils;
 
@@ -79,6 +80,11 @@
         cram.initialise(this);
         _saslServers.put(cram.getMechanismName(), cram);
 
+        //Add the Hex initialiser
+        CRAMMD5HexInitialiser cramHex = new CRAMMD5HexInitialiser();
+        cramHex.initialise(this);
+        _saslServers.put(cramHex.getMechanismName(), cramHex);
+
         //fixme The PDs should setup a PD Mangement MBean
 //        try
 //        {

Added: qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/crammd5/CRAMMD5HexInitialiser.java
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/crammd5/CRAMMD5HexInitialiser.java?rev=884838&view=auto
==============================================================================
--- qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/crammd5/CRAMMD5HexInitialiser.java (added)
+++ qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/crammd5/CRAMMD5HexInitialiser.java Fri Nov 27 11:44:54 2009
@@ -0,0 +1,144 @@
+/*
+ *
+ * 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.server.security.auth.sasl.crammd5;
+
+import org.apache.qpid.server.security.auth.database.PrincipalDatabase;
+import org.apache.qpid.server.security.auth.sasl.UsernamePasswordInitialiser;
+import org.apache.qpid.server.security.auth.sasl.AuthenticationProviderInitialiser;
+
+import javax.security.sasl.SaslServerFactory;
+import javax.security.auth.callback.PasswordCallback;
+import javax.security.auth.login.AccountNotFoundException;
+import java.util.Map;
+import java.util.List;
+import java.security.Principal;
+import java.io.IOException;
+
+public class CRAMMD5HexInitialiser extends UsernamePasswordInitialiser
+{
+    public String getMechanismName()
+    {
+        return CRAMMD5HexSaslServer.MECHANISM;
+    }
+
+    public Class<? extends SaslServerFactory> getServerFactoryClassForJCARegistration()
+    {
+        return CRAMMD5HexServerFactory.class;
+    }
+
+    public Map<String, ?> getProperties()
+    {
+        return null;
+    }
+
+    public void initialise(PrincipalDatabase db)
+    {
+        super.initialise(new HexifyPrincipalDatabase(db));
+
+    }
+
+    private class HexifyPrincipalDatabase implements PrincipalDatabase
+    {
+        private PrincipalDatabase _realPricipalDatabase;
+
+        HexifyPrincipalDatabase(PrincipalDatabase db)
+        {
+            _realPricipalDatabase = db;
+        }
+
+        private char[] toHex(char[] password)
+        {
+            StringBuilder sb = new StringBuilder();
+            for (char c : password)
+            {
+                //toHexString does not prepend 0 so we have to
+                if (((byte) c > -1) && (byte) c < 10)
+                {
+                    sb.append(0);
+                }
+
+                sb.append(Integer.toHexString(c & 0xFF));
+            }
+
+            //Extract the hex string as char[]
+            char[] hex = new char[sb.length()];
+
+            sb.getChars(0, sb.length(), hex, 0);
+
+            return hex;
+        }
+
+        public void setPassword(Principal principal, PasswordCallback callback) throws IOException, AccountNotFoundException
+        {
+            //Let the read DB set the password
+            _realPricipalDatabase.setPassword(principal, callback);
+
+            //Retrieve the setpassword
+            char[] plainPassword = callback.getPassword();
+
+            char[] hexPassword = toHex(plainPassword);
+
+            callback.setPassword(hexPassword);
+        }
+
+        // Simply delegate to the real PrincipalDB
+        public boolean verifyPassword(String principal, char[] password) throws AccountNotFoundException
+        {
+            return _realPricipalDatabase.verifyPassword(principal, password);
+        }
+
+        public boolean updatePassword(Principal principal, char[] password) throws AccountNotFoundException
+        {
+            return _realPricipalDatabase.updatePassword(principal, password);
+        }
+
+        public boolean createPrincipal(Principal principal, char[] password)
+        {
+            return _realPricipalDatabase.createPrincipal(principal, password);
+        }
+
+        public boolean deletePrincipal(Principal principal) throws AccountNotFoundException
+        {
+            return _realPricipalDatabase.deletePrincipal(principal);
+        }
+
+        public Principal getUser(String username)
+        {
+            return _realPricipalDatabase.getUser(username);
+        }
+
+        public Map<String, AuthenticationProviderInitialiser> getMechanisms()
+        {
+            return _realPricipalDatabase.getMechanisms();
+        }
+
+        public List<Principal> getUsers()
+        {
+            return _realPricipalDatabase.getUsers();
+        }
+	
+        public void reload() throws IOException
+        {
+            _realPricipalDatabase.reload();
+        }
+    }
+
+}

Added: qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/crammd5/CRAMMD5HexSaslServer.java
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/crammd5/CRAMMD5HexSaslServer.java?rev=884838&view=auto
==============================================================================
--- qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/crammd5/CRAMMD5HexSaslServer.java (added)
+++ qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/crammd5/CRAMMD5HexSaslServer.java Fri Nov 27 11:44:54 2009
@@ -0,0 +1,105 @@
+/*
+ *  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.server.security.auth.sasl.crammd5;
+
+import javax.security.sasl.SaslServer;
+import javax.security.sasl.SaslException;
+import javax.security.sasl.Sasl;
+import javax.security.sasl.SaslServerFactory;
+import javax.security.auth.callback.CallbackHandler;
+import java.util.Enumeration;
+import java.util.Map;
+
+public class CRAMMD5HexSaslServer implements SaslServer
+{
+    public static final String MECHANISM = "CRAM-MD5-HEX";
+
+    private SaslServer _realServer;
+
+    public CRAMMD5HexSaslServer(String mechanism, String protocol, String serverName, Map<String, ?> props,
+                                   CallbackHandler cbh) throws SaslException
+    {
+        Enumeration factories = Sasl.getSaslServerFactories();
+
+        while (factories.hasMoreElements())
+        {
+            SaslServerFactory factory = (SaslServerFactory) factories.nextElement();
+
+            if (factory instanceof CRAMMD5HexServerFactory)
+            {
+                continue;
+            }
+            
+            String[] mechs = factory.getMechanismNames(props);
+
+            for (String mech : mechs)
+            {
+                if (mech.equals("CRAM-MD5"))
+                {
+                    _realServer = factory.createSaslServer("CRAM-MD5", protocol, serverName, props, cbh);
+                    return;
+                }
+            }
+        }
+
+        throw new RuntimeException("No default SaslServer found for mechanism:" + "CRAM-MD5");
+    }
+
+    public String getMechanismName()
+    {
+        return MECHANISM;
+    }
+
+    public byte[] evaluateResponse(byte[] response) throws SaslException
+    {
+        return _realServer.evaluateResponse(response);
+    }
+
+    public boolean isComplete()
+    {
+        return _realServer.isComplete();
+    }
+
+    public String getAuthorizationID()
+    {
+        return _realServer.getAuthorizationID();
+    }
+
+    public byte[] unwrap(byte[] incoming, int offset, int len) throws SaslException
+    {
+        return _realServer.unwrap(incoming, offset, len);
+    }
+
+    public byte[] wrap(byte[] outgoing, int offset, int len) throws SaslException
+    {
+        return _realServer.wrap(outgoing, offset, len);
+    }
+
+    public Object getNegotiatedProperty(String propName)
+    {
+        return _realServer.getNegotiatedProperty(propName);
+    }
+
+    public void dispose() throws SaslException
+    {
+        _realServer.dispose();
+    }
+}

Added: qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/crammd5/CRAMMD5HexServerFactory.java
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/crammd5/CRAMMD5HexServerFactory.java?rev=884838&view=auto
==============================================================================
--- qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/crammd5/CRAMMD5HexServerFactory.java (added)
+++ qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/crammd5/CRAMMD5HexServerFactory.java Fri Nov 27 11:44:54 2009
@@ -0,0 +1,61 @@
+/*
+ *
+ * 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.server.security.auth.sasl.crammd5;
+
+import java.util.Map;
+
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.sasl.Sasl;
+import javax.security.sasl.SaslException;
+import javax.security.sasl.SaslServer;
+import javax.security.sasl.SaslServerFactory;
+
+public class CRAMMD5HexServerFactory implements SaslServerFactory
+{
+    public SaslServer createSaslServer(String mechanism, String protocol, String serverName, Map<String, ?> props,
+                                       CallbackHandler cbh) throws SaslException
+    {
+        if (mechanism.equals(CRAMMD5HexSaslServer.MECHANISM))
+        {
+            return new CRAMMD5HexSaslServer(mechanism, protocol, serverName, props, cbh);
+        }
+        else
+        {
+            return null;
+        }
+    }
+
+    public String[] getMechanismNames(Map props)
+    {
+        if (props != null)
+        {
+            if (props.containsKey(Sasl.POLICY_NOPLAINTEXT) ||
+                props.containsKey(Sasl.POLICY_NODICTIONARY) ||
+                props.containsKey(Sasl.POLICY_NOACTIVE))
+            {
+                // returned array must be non null according to interface documentation
+                return new String[0];
+            }
+        }
+
+        return new String[]{CRAMMD5HexSaslServer.MECHANISM};
+    }
+}

Added: qpid/trunk/qpid/java/broker/src/test/java/org/apache/qpid/server/securiity/auth/sasl/CRAMMD5HexInitialiserTest.java
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/broker/src/test/java/org/apache/qpid/server/securiity/auth/sasl/CRAMMD5HexInitialiserTest.java?rev=884838&view=auto
==============================================================================
--- qpid/trunk/qpid/java/broker/src/test/java/org/apache/qpid/server/securiity/auth/sasl/CRAMMD5HexInitialiserTest.java (added)
+++ qpid/trunk/qpid/java/broker/src/test/java/org/apache/qpid/server/securiity/auth/sasl/CRAMMD5HexInitialiserTest.java Fri Nov 27 11:44:54 2009
@@ -0,0 +1,143 @@
+/*
+ *
+ * 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.server.securiity.auth.sasl;
+
+import junit.framework.TestCase;
+import org.apache.qpid.server.security.auth.database.PropertiesPrincipalDatabase;
+import org.apache.qpid.server.security.auth.sasl.crammd5.CRAMMD5HexInitialiser;
+
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.NameCallback;
+import javax.security.auth.callback.PasswordCallback;
+import javax.security.auth.callback.UnsupportedCallbackException;
+import java.io.IOException;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.Properties;
+
+/**
+ * These tests ensure that the Hex wrapping that the initialiser performs does actually operate when the handle method is called.
+ */
+public class CRAMMD5HexInitialiserTest extends TestCase
+{
+
+    public void testHex()
+    {
+
+        //Create User details for testing
+        String user = "testUser";
+        String password = "testPassword";
+
+        perform(user, password);
+    }
+
+    public void testHashedHex()
+    {
+
+        //Create User details for testing
+        String user = "testUser";
+        String password = "testPassword";
+
+        //Create a hashed password that we then attempt to put through the call back mechanism.
+        try
+        {
+            password = new String(MessageDigest.getInstance("MD5").digest(password.getBytes()));
+        }
+        catch (NoSuchAlgorithmException e)
+        {
+            fail(e.getMessage());
+        }
+
+        perform(user, password);
+    }
+
+    public void perform(String user, String password)
+    {
+        CRAMMD5HexInitialiser initialiser = new CRAMMD5HexInitialiser();
+
+        //Use properties to create a PrincipalDatabase
+        Properties users = new Properties();
+        users.put(user, password);
+
+        PropertiesPrincipalDatabase db = new PropertiesPrincipalDatabase(users);
+
+        initialiser.initialise(db);
+
+        //setup the callbacks
+        PasswordCallback passwordCallback = new PasswordCallback("password:", false);
+        NameCallback usernameCallback = new NameCallback("user:", user);
+
+        Callback[] callbacks = new Callback[]{usernameCallback, passwordCallback};
+
+        //Check the
+        try
+        {
+            assertNull("The password was not null before the handle call.", passwordCallback.getPassword());
+            initialiser.getCallbackHandler().handle(callbacks);
+        }
+        catch (IOException e)
+        {
+            fail(e.getMessage());
+        }
+        catch (UnsupportedCallbackException e)
+        {
+            fail(e.getMessage());
+        }
+
+        //Hex the password we initialised with and compare it with the passwordCallback
+        assertArrayEquals(toHex(password.toCharArray()), passwordCallback.getPassword());
+
+    }
+
+    private void assertArrayEquals(char[] expected, char[] actual)
+    {        
+        assertEquals("Arrays are not the same length", expected.length, actual.length);
+
+        for (int index = 0; index < expected.length; index++)
+        {
+            assertEquals("Characters are not equal", expected[index], actual[index]);
+        }
+    }
+
+    private char[] toHex(char[] password)
+    {
+        StringBuilder sb = new StringBuilder();
+        for (char c : password)
+        {
+            //toHexString does not prepend 0 so we have to
+            if (((byte) c > -1) && (byte) c < 10)
+            {
+                sb.append(0);
+            }
+
+            sb.append(Integer.toHexString(c & 0xFF));
+        }
+
+        //Extract the hex string as char[]
+        char[] hex = new char[sb.length()];
+
+        sb.getChars(0, sb.length(), hex, 0);
+
+        return hex;
+    }
+    
+
+}



---------------------------------------------------------------------
Apache Qpid - AMQP Messaging Implementation
Project:      http://qpid.apache.org
Use/Interact: mailto:commits-subscribe@qpid.apache.org