diff options
author | Martin Ritchie <ritchiem@apache.org> | 2007-04-11 13:31:18 +0000 |
---|---|---|
committer | Martin Ritchie <ritchiem@apache.org> | 2007-04-11 13:31:18 +0000 |
commit | 786f4c78363db63f613f5d792d5f4465027e111b (patch) | |
tree | f4dc03210d786a236876bfd4c59c6504eae6cf30 | |
parent | c9aeb7dcd4cba2f47b0df7062108ef0b837c43bc (diff) | |
download | qpid-python-786f4c78363db63f613f5d792d5f4465027e111b.tar.gz |
QPID-446 AMQUserManagementMBean Initial implementation of user management in authentication file.
UserManagement - Added annotations for MBeanOperations
PrincipalDatabase - Added new methods to update,create,delete Principal.
- Implemented method on all PrincipalDatabase implementations, most return false to say not complete except
Base64MD5PasswordFilePrincipalDatabase - which now stores in memory the password file and flushes any changes to disk.
git-svn-id: https://svn.apache.org/repos/asf/incubator/qpid/branches/M2@527487 13f79535-47bb-0310-9956-ffa450edef68
7 files changed, 561 insertions, 67 deletions
diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/access/AMQUserManagementMBean.java b/java/broker/src/main/java/org/apache/qpid/server/security/access/AMQUserManagementMBean.java index 452479a3ba..c8b4c92a60 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/security/access/AMQUserManagementMBean.java +++ b/java/broker/src/main/java/org/apache/qpid/server/security/access/AMQUserManagementMBean.java @@ -24,15 +24,33 @@ import org.apache.qpid.server.management.MBeanDescription; import org.apache.qpid.server.management.AMQManagedObject; import org.apache.qpid.server.management.MBeanOperationParameter; import org.apache.qpid.server.management.MBeanOperation; +import org.apache.qpid.server.security.auth.database.PrincipalDatabase; +import org.apache.qpid.server.security.auth.sasl.UsernamePrincipal; +import org.apache.log4j.Logger; import javax.management.JMException; import javax.management.openmbean.TabularData; +import javax.security.auth.login.AccountNotFoundException; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.util.Properties; +import java.util.Map; +import java.util.HashMap; +import java.security.Principal; /** MBean class for AMQUserManagementMBean. It implements all the management features exposed for managing users. */ @MBeanDescription("User Management Interface") public class AMQUserManagementMBean extends AMQManagedObject implements UserManagement { + private static final Logger _logger = Logger.getLogger(AMQUserManagementMBean.class); + + private PrincipalDatabase _principalDatabase; + private File _accessFile; + + Map<String, Principal> _users = new HashMap<String, Principal>(); + public AMQUserManagementMBean() throws JMException { super(UserManagement.class, UserManagement.TYPE); @@ -43,24 +61,84 @@ public class AMQUserManagementMBean extends AMQManagedObject implements UserMana return UserManagement.TYPE; } - public boolean setPassword(@MBeanOperationParameter(name = "username", description = "Username")String username, @MBeanOperationParameter(name = "password", description = "Password")String password) + public boolean setPassword(@MBeanOperationParameter(name = "username", description = "Username")String username, + @MBeanOperationParameter(name = "password", description = "Password")String password) { - return true; + try + { + return _principalDatabase.updatePassword(new UsernamePrincipal(username), password); + } + catch (AccountNotFoundException e) + { + _logger.warn("Attempt to set password of non-existant user'" + username + "'"); + return false; + } } - public boolean setRights(@MBeanOperationParameter(name = "username", description = "Username")String username, @MBeanOperationParameter(name = "read", description = "Administration read")boolean read, @MBeanOperationParameter(name = "write", description = "Administration write")boolean write, @MBeanOperationParameter(name = "admin", description = "Administration rights")boolean admin) + public boolean setRights(@MBeanOperationParameter(name = "username", description = "Username")String username, + @MBeanOperationParameter(name = "read", description = "Administration read")boolean read, + @MBeanOperationParameter(name = "write", description = "Administration write")boolean write, + @MBeanOperationParameter(name = "admin", description = "Administration rights")boolean admin) { return true; } - public boolean createUser(@MBeanOperationParameter(name = "username", description = "Username")String username, @MBeanOperationParameter(name = "password", description = "Password")String password, @MBeanOperationParameter(name = "read", description = "Administration read")boolean read, @MBeanOperationParameter(name = "write", description = "Administration write")boolean write, @MBeanOperationParameter(name = "admin", description = "Administration rights")boolean admin) + public boolean createUser(@MBeanOperationParameter(name = "username", description = "Username")String username, + @MBeanOperationParameter(name = "password", description = "Password")String password, + @MBeanOperationParameter(name = "read", description = "Administration read")boolean read, + @MBeanOperationParameter(name = "write", description = "Administration write")boolean write, + @MBeanOperationParameter(name = "admin", description = "Administration rights")boolean admin) { - return true; + try + { + if (_principalDatabase.createPrincipal(new UsernamePrincipal(username), password)) + { + _users.remove(username); + return true; + } + } + catch (AccountNotFoundException e) + { + _logger.warn("Attempt to delete user (" + username + ") that doesn't exist"); + } + + return false; } public boolean deleteUser(@MBeanOperationParameter(name = "username", description = "Username")String username) { - return true; + + try + { + if (_principalDatabase.deletePrincipal(new UsernamePrincipal(username))) + { + _users.remove(username); + return true; + } + } + catch (AccountNotFoundException e) + { + _logger.warn("Attempt to delete user (" + username + ") that doesn't exist"); + } + + return false; + } + + public boolean reloadData() + { + try + { + loadAccessFile(); + + // Reload successful + return true; + } + catch (IOException e) + { + _logger.info("Reload failed due to:" + e); + // Reload unsuccessful + return false; + } } @MBeanOperation(name = "viewUsers", description = "All users with access rights to the system.") @@ -68,4 +146,57 @@ public class AMQUserManagementMBean extends AMQManagedObject implements UserMana { return null; } + + /*** Broker Methods **/ + + /** + * setPrincipalDatabase + * + * @param database + * + * @throws java.io.IOException If the file cannot be read + */ + public void setPrincipalDatabase(PrincipalDatabase database) + { + _principalDatabase = database; + } + + /** + * setAccessFile + * + * @param accessFile the file to use for updating. + * + * @throws java.io.IOException If the file cannot be read + */ + public void setAccessFile(File accessFile) throws IOException + { + _accessFile = accessFile; + + if (_accessFile != null) + { + loadAccessFile(); + } + else + { + _logger.warn("Access rights file specified is null. Access rights not changed."); + } + } + + private void loadAccessFile() throws IOException + { + Properties accessRights = new Properties(); + accessRights.load(new FileInputStream(_accessFile)); + processAccessRights(accessRights); + + } + + /** + * user=read user=write user=readwrite user=admin + * + * @param accessRights The properties list of access rights to process + */ + private void processAccessRights(Properties accessRights) + { + //To change body of created methods use File | Settings | File Templates. + } } diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/access/UserManagement.java b/java/broker/src/main/java/org/apache/qpid/server/security/access/UserManagement.java index e18d49a6d7..a29da431ef 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/security/access/UserManagement.java +++ b/java/broker/src/main/java/org/apache/qpid/server/security/access/UserManagement.java @@ -35,8 +35,6 @@ public interface UserManagement String TYPE = "UserManagement"; //********** Operations *****************// - - /** * set password for user * @@ -45,6 +43,7 @@ public interface UserManagement * * @return The result of the operation */ + @MBeanOperation(name = "setPassword", description = "Set password for user.") boolean setPassword(@MBeanOperationParameter(name = "username", description = "Username")String username, @MBeanOperationParameter(name = "password", description = "Password")String password); @@ -58,6 +57,7 @@ public interface UserManagement * * @return The result of the operation */ + @MBeanOperation(name = "setRights", description = "Set access rights for user.") boolean setRights(@MBeanOperationParameter(name = "username", description = "Username")String username, @MBeanOperationParameter(name = "read", description = "Administration read")boolean read, @MBeanOperationParameter(name = "write", description = "Administration write")boolean write, @@ -74,6 +74,7 @@ public interface UserManagement * * @return The result of the operation */ + @MBeanOperation(name = "createUser", description = "Create new user from system.") boolean createUser(@MBeanOperationParameter(name = "username", description = "Username")String username, @MBeanOperationParameter(name = "password", description = "Password")String password, @MBeanOperationParameter(name = "read", description = "Administration read")boolean read, @@ -87,8 +88,18 @@ public interface UserManagement * * @return The result of the operation */ + @MBeanOperation(name = "deleteUser", description = "Delete user from system.") boolean deleteUser(@MBeanOperationParameter(name = "username", description = "Username")String username); + + /** + * Reload the date from disk + * + * @return The result of the operation + */ + @MBeanOperation(name = "reloadData", description = "Reload the authentication file from disk.") + boolean reloadData(); + /** * View users returns all the users that are currently available to the system. * diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/Base64MD5PasswordFilePrincipalDatabase.java b/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/Base64MD5PasswordFilePrincipalDatabase.java index c603a0d5c3..1fd86f0bac 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/Base64MD5PasswordFilePrincipalDatabase.java +++ b/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/Base64MD5PasswordFilePrincipalDatabase.java @@ -23,19 +23,29 @@ package org.apache.qpid.server.security.auth.database; import org.apache.log4j.Logger; import org.apache.qpid.server.security.auth.sasl.AuthenticationProviderInitialiser; import org.apache.qpid.server.security.auth.sasl.crammd5.CRAMMD5HashedInitialiser; +import org.apache.qpid.server.security.access.AMQUserManagementMBean; +import org.apache.qpid.server.security.Passwd; import org.apache.commons.codec.binary.Base64; +import org.apache.commons.codec.EncoderException; import javax.security.auth.callback.PasswordCallback; import javax.security.auth.login.AccountNotFoundException; +import javax.management.JMException; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.io.BufferedReader; import java.io.FileReader; +import java.io.UnsupportedEncodingException; +import java.io.BufferedWriter; +import java.io.FileWriter; +import java.io.PrintStream; import java.util.regex.Pattern; import java.util.Map; import java.util.HashMap; +import java.util.List; import java.security.Principal; +import java.security.NoSuchAlgorithmException; /** * Represents a user database where the account information is stored in a simple flat file. @@ -54,6 +64,10 @@ public class Base64MD5PasswordFilePrincipalDatabase implements PrincipalDatabase private Map<String, AuthenticationProviderInitialiser> _saslServers; + AMQUserManagementMBean _mbean; + private static final String DEFAULT_ENCODING = "utf-8"; + private Map<String, User> _users = new HashMap<String, User>(); + public Base64MD5PasswordFilePrincipalDatabase() { _saslServers = new HashMap<String, AuthenticationProviderInitialiser>(); @@ -66,9 +80,19 @@ public class Base64MD5PasswordFilePrincipalDatabase implements PrincipalDatabase CRAMMD5HashedInitialiser cram = new CRAMMD5HashedInitialiser(); cram.initialise(this); _saslServers.put(cram.getMechanismName(), cram); + + try + { + _mbean = new AMQUserManagementMBean(); + _mbean.setPrincipalDatabase(this); + } + catch (JMException e) + { + _logger.warn("User management disabled as unable to create MBean:" + e); + } } - public void setPasswordFile(String passwordFile) throws FileNotFoundException + public void setPasswordFile(String passwordFile) throws IOException { File f = new File(passwordFile); _logger.info("PasswordFilePrincipalDatabase using file " + f.getAbsolutePath()); @@ -82,10 +106,11 @@ public class Base64MD5PasswordFilePrincipalDatabase implements PrincipalDatabase throw new FileNotFoundException("Cannot read password file " + f + ". Check permissions."); } + + loadPasswordFile(); } - public void setPassword(Principal principal, PasswordCallback callback) throws IOException, - AccountNotFoundException + public void setPassword(Principal principal, PasswordCallback callback) throws AccountNotFoundException { if (_passwordFile == null) { @@ -95,7 +120,9 @@ public class Base64MD5PasswordFilePrincipalDatabase implements PrincipalDatabase { throw new IllegalArgumentException("principal must not be null"); } + char[] pwd = lookupPassword(principal.getName()); + if (pwd != null) { callback.setPassword(pwd); @@ -106,55 +133,169 @@ public class Base64MD5PasswordFilePrincipalDatabase implements PrincipalDatabase } } - public boolean verifyPassword(Principal principal, char[] password) throws AccountNotFoundException + public boolean verifyPassword(Principal principal, String password) throws AccountNotFoundException { try { char[] pwd = lookupPassword(principal.getName()); - return compareCharArray(pwd, password); + byte[] passwordBytes = password.getBytes(DEFAULT_ENCODING); + + int index = 0; + boolean verified = true; + + while (verified & index < passwordBytes.length) + { + verified = (pwd[index] == (char) passwordBytes[index]); + index++; + } + return verified; } - catch (IOException e) + catch (UnsupportedEncodingException e) { return false; } } - public Map<String, AuthenticationProviderInitialiser> getMechanisms() + public boolean updatePassword(Principal principal, String password) throws AccountNotFoundException { - return _saslServers; - } + User user = _users.get(principal.getName()); - private boolean compareCharArray(char[] a, char[] b) - { - boolean equal = false; - if (a.length == b.length) + if (user == null) { - equal = true; - int index = 0; - while (equal && index < a.length) + throw new AccountNotFoundException(principal.getName()); + } + + try + { + + char[] passwd = convertPassword(password); + + user.setPassword(passwd); + + try { - equal = a[index] == b[index]; - index++; + savePasswordFile(); } + catch (IOException e) + { + _logger.error("Unable to save password file, password change for user'" + + principal + "' will revert at restart"); + return false; + } + return true; + } + catch (UnsupportedEncodingException e) + { + return false; } - return equal; } + private char[] convertPassword(String password) throws UnsupportedEncodingException + { + byte[] passwdBytes = password.getBytes(DEFAULT_ENCODING); + + char[] passwd = new char[passwdBytes.length]; + + int index = 0; + + for (byte b : passwdBytes) + { + passwd[index] = (char) b; + } + + return passwd; + } + + public boolean createPrincipal(Principal principal, String password) throws AccountNotFoundException + { + if (_users.get(principal.getName()) != null) + { + return false; + } + + User user = null; + try + { + user = new User(principal.getName(), convertPassword(password)); + } + catch (UnsupportedEncodingException e) + { + _logger.warn("Unable to encode password:" + e); + return false; + } + + _users.put(user.getName(), user); + + try + { + savePasswordFile(); + return true; + } + catch (IOException e) + { + return false; + } + + } + + public boolean deletePrincipal(Principal principal) throws AccountNotFoundException + { + User user = _users.get(principal.getName()); + + if (user == null) + { + throw new AccountNotFoundException(principal.getName()); + } + + user.delete(); + + try + { + savePasswordFile(); + } + catch (IOException e) + { + _logger.warn("Unable to remove user '" + user.getName() + "' from password file."); + return false; + } + + _users.remove(user.getName()); + + return true; + } + + public Map<String, AuthenticationProviderInitialiser> getMechanisms() + { + return _saslServers; + } /** * Looks up the password for a specified user in the password file. Note this code is <b>not</b> secure since it * creates strings of passwords. It should be modified to create only char arrays which get nulled out. * - * @param name + * @param name The principal name to lookup * - * @return - * - * @throws java.io.IOException + * @return a char[] for use in SASL. */ - private char[] lookupPassword(String name) throws IOException + private char[] lookupPassword(String name) + { + User user = _users.get(name); + if (user == null) + { + return null; + } + else + { + return user.getPassword(); + } + } + + + private void loadPasswordFile() throws IOException { + _users.clear(); + BufferedReader reader = null; - byte[] passwd = null; try { reader = new BufferedReader(new FileReader(_passwordFile)); @@ -163,43 +304,75 @@ public class Base64MD5PasswordFilePrincipalDatabase implements PrincipalDatabase while ((line = reader.readLine()) != null) { String[] result = _regexp.split(line); - if (result == null || result.length < 2) + if (result == null || result.length < 2 || result[0].startsWith("#")) { continue; } - if (name.equals(result[0])) - { + User user = new User(result); + _users.put(user.getName(), user); + } + } + finally + { + if (reader != null) + { + reader.close(); + } + } + } + private void savePasswordFile() throws IOException + { + BufferedReader reader = null; + PrintStream writer = null; + File tmp = new File(_passwordFile.getAbsolutePath() + ".tmp"); + try + { + writer = new PrintStream(tmp); + reader = new BufferedReader(new FileReader(_passwordFile)); + String line; - char[] raw = result[1].toCharArray(); + while ((line = reader.readLine()) != null) + { + String[] result = _regexp.split(line); + if (result == null || result.length < 2 || result[0].startsWith("#")) + { + writer.write(line.getBytes(DEFAULT_ENCODING)); + continue; + } - byte[] encoded = new byte[result[1].length() + 1]; + User user = _users.get(result[0]); - int index = 0; - for (char c : raw) + if (user == null) + { + writer.write(line.getBytes(DEFAULT_ENCODING)); + } + else if (!user.isDeleted()) + { + if (!user.isModified()) { - index++; - encoded[index] = (byte) c; + writer.write(line.getBytes(DEFAULT_ENCODING)); } - - Base64 b64 = new Base64(); - byte[] decoded = b64.decode(encoded); - - - char[] hashedPassword = new char[decoded.length + 1]; - - index = 0; - for (byte c : decoded) + else { - index++; - hashedPassword[index] = (char) c; - } + try + { + byte[] encodedPassword = user.getEncodePassword(); - return hashedPassword; + writer.write((user.getName() + ":").getBytes(DEFAULT_ENCODING)); + writer.write(encodedPassword); + } + catch (EncoderException e) + { + _logger.warn("Unable to encode new password reverting to old password."); + writer.write(line.getBytes(DEFAULT_ENCODING)); + } + } } + + } - return null; } finally { @@ -207,6 +380,102 @@ public class Base64MD5PasswordFilePrincipalDatabase implements PrincipalDatabase { reader.close(); } + + if (writer != null) + { + writer.close(); + } + + // Swap temp file to main password file. + tmp.renameTo(_passwordFile); + } + } + + private class User + { + String _name; + char[] _password; + byte[] _encodedPassword = null; + private boolean _modified = false; + private boolean _deleted = false; + + User(String[] data) throws UnsupportedEncodingException + { + if (data.length != 2) + { + throw new IllegalArgumentException("User Data should be lenght 2, username, password"); + } + + _name = data[0]; + + byte[] encoded_password = data[1].getBytes(DEFAULT_ENCODING); + + Base64 b64 = new Base64(); + byte[] decoded = b64.decode(encoded_password); + + _encodedPassword = encoded_password; + + _password = new char[decoded.length]; + + int index = 0; + for (byte c : decoded) + { + _password[index++] = (char) c; + } + } + + public User(String name, char[] password) + { + _name = name; + setPassword(password); + } + + String getName() + { + return _name; + } + + char[] getPassword() + { + return _password; + } + + void setPassword(char[] password) + { + _password = password; + _modified = true; + _encodedPassword = null; + } + + + byte[] getEncodePassword() throws EncoderException, UnsupportedEncodingException + { + if (_encodedPassword == null) + { + encodePassword(); + } + return _encodedPassword; + } + + private void encodePassword() throws EncoderException, UnsupportedEncodingException + { + Base64 b64 = new Base64(); + _encodedPassword = b64.encode(new String(_password).getBytes(DEFAULT_ENCODING)); + } + + public boolean isModified() + { + return _modified; + } + + public boolean isDeleted() + { + return _deleted; + } + + public void delete() + { + _deleted = true; } } } diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/PlainPasswordFilePrincipalDatabase.java b/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/PlainPasswordFilePrincipalDatabase.java index fc20b0693b..ac7bfa29a3 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/PlainPasswordFilePrincipalDatabase.java +++ b/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/PlainPasswordFilePrincipalDatabase.java @@ -34,6 +34,7 @@ import java.io.FileNotFoundException; import java.io.IOException; import java.io.BufferedReader; import java.io.FileReader; +import java.io.UnsupportedEncodingException; import java.util.regex.Pattern; import java.util.Map; import java.util.HashMap; @@ -119,12 +120,13 @@ public class PlainPasswordFilePrincipalDatabase implements PrincipalDatabase } } - public boolean verifyPassword(Principal principal, char[] password) throws AccountNotFoundException + public boolean verifyPassword(Principal principal, String password) throws AccountNotFoundException { try { char[] pwd = lookupPassword(principal.getName()); - return compareCharArray(pwd, password); + + return compareCharArray(pwd, convertPassword(password)); } catch (IOException e) { @@ -132,6 +134,37 @@ public class PlainPasswordFilePrincipalDatabase implements PrincipalDatabase } } + private char[] convertPassword(String password) throws UnsupportedEncodingException + { + byte[] passwdBytes = password.getBytes("utf-8"); + + char[] passwd = new char[passwdBytes.length]; + + int index = 0; + + for (byte b : passwdBytes) + { + passwd[index] = (char) b; + } + + return passwd; + } + + public boolean updatePassword(Principal principal, String password) throws AccountNotFoundException + { + return false; // updates denied + } + + public boolean createPrincipal(Principal principal, String password) throws AccountNotFoundException + { + return false; // updates denied + } + + public boolean deletePrincipal(Principal principal) throws AccountNotFoundException + { + return false; // updates denied + } + public Map<String, AuthenticationProviderInitialiser> getMechanisms() { return _saslServers; diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/PrincipalDatabase.java b/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/PrincipalDatabase.java index 32ef9cc0d2..50a2845b4f 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/PrincipalDatabase.java +++ b/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/PrincipalDatabase.java @@ -23,6 +23,7 @@ package org.apache.qpid.server.security.auth.database; import org.apache.qpid.server.security.auth.sasl.AuthenticationProviderInitialiser; import java.io.IOException; +import java.io.UnsupportedEncodingException; import java.security.Principal; import java.util.Map; @@ -46,7 +47,7 @@ public interface PrincipalDatabase void setPassword(Principal principal, PasswordCallback callback) throws IOException, AccountNotFoundException; - /** + /** * Set the password for a given principal in the specified callback. This is used for certain SASL providers. The * user database implementation should look up the password in any way it chooses and set it in the callback by * calling its setPassword method. @@ -54,10 +55,20 @@ public interface PrincipalDatabase * @param principal the principal * @param password the password to be verified * - * @throws AccountNotFoundException if the account for specified principal could not be found * @return true if the account is verified. + * + * @throws AccountNotFoundException if the account for specified principal could not be found */ - boolean verifyPassword(Principal principal, char[] password) + boolean verifyPassword(Principal principal, String password) + throws AccountNotFoundException; + + boolean updatePassword(Principal principal, String password) + throws AccountNotFoundException; + + boolean createPrincipal(Principal principal, String password) + throws AccountNotFoundException; + + boolean deletePrincipal(Principal principal) throws AccountNotFoundException; public Map<String, AuthenticationProviderInitialiser> getMechanisms(); diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/PropertiesPrincipalDatabase.java b/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/PropertiesPrincipalDatabase.java index f5332b6e6b..86d7ed40ee 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/PropertiesPrincipalDatabase.java +++ b/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/PropertiesPrincipalDatabase.java @@ -31,6 +31,7 @@ import java.util.Map; import java.util.HashMap; import java.security.Principal; import java.io.IOException; +import java.io.UnsupportedEncodingException; public class PropertiesPrincipalDatabase implements PrincipalDatabase { @@ -76,11 +77,33 @@ public class PropertiesPrincipalDatabase implements PrincipalDatabase } } - public boolean verifyPassword(Principal principal, char[] password) throws AccountNotFoundException + public boolean verifyPassword(Principal principal, String password) throws AccountNotFoundException { char[] pwd = _users.getProperty(principal.getName()).toCharArray(); - return compareCharArray(pwd, password); + try + { + return compareCharArray(pwd, convertPassword(password)); + } + catch (UnsupportedEncodingException e) + { + return false; + } + } + + public boolean updatePassword(Principal principal, String password) throws AccountNotFoundException + { + return false; // updates denied + } + + public boolean createPrincipal(Principal principal, String password) throws AccountNotFoundException + { + return false; // updates denied + } + + public boolean deletePrincipal(Principal principal) throws AccountNotFoundException + { + return false; // updates denied } private boolean compareCharArray(char[] a, char[] b) @@ -99,6 +122,23 @@ public class PropertiesPrincipalDatabase implements PrincipalDatabase return equal; } + private char[] convertPassword(String password) throws UnsupportedEncodingException + { + byte[] passwdBytes = password.getBytes("utf-8"); + + char[] passwd = new char[passwdBytes.length]; + + int index = 0; + + for (byte b : passwdBytes) + { + passwd[index] = (char) b; + } + + return passwd; + } + + public Map<String, AuthenticationProviderInitialiser> getMechanisms() { return _saslServers; diff --git a/java/client/src/main/java/org/apache/qpid/client/security/UsernameHashedPasswordCallbackHandler.java b/java/client/src/main/java/org/apache/qpid/client/security/UsernameHashedPasswordCallbackHandler.java index dcca55e6c2..46323e8c09 100644 --- a/java/client/src/main/java/org/apache/qpid/client/security/UsernameHashedPasswordCallbackHandler.java +++ b/java/client/src/main/java/org/apache/qpid/client/security/UsernameHashedPasswordCallbackHandler.java @@ -91,13 +91,12 @@ public class UsernameHashedPasswordCallbackHandler implements AMQCallbackHandler byte[] digest = md.digest(); - char[] hash = new char[digest.length + 1]; + char[] hash = new char[digest.length ]; int index = 0; for (byte b : digest) - { - index++; - hash[index] = (char) b; + { + hash[index++] = (char) b; } return hash; |