Return-Path: Delivered-To: apmail-incubator-qpid-commits-archive@locus.apache.org Received: (qmail 30381 invoked from network); 19 Apr 2007 16:25:27 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (140.211.11.2) by minotaur.apache.org with SMTP; 19 Apr 2007 16:25:27 -0000 Received: (qmail 48582 invoked by uid 500); 19 Apr 2007 16:25:33 -0000 Delivered-To: apmail-incubator-qpid-commits-archive@incubator.apache.org Received: (qmail 48558 invoked by uid 500); 19 Apr 2007 16:25:33 -0000 Mailing-List: contact qpid-commits-help@incubator.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: qpid-dev@incubator.apache.org Delivered-To: mailing list qpid-commits@incubator.apache.org Received: (qmail 48540 invoked by uid 99); 19 Apr 2007 16:25:33 -0000 Received: from herse.apache.org (HELO herse.apache.org) (140.211.11.133) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 19 Apr 2007 09:25:33 -0700 X-ASF-Spam-Status: No, hits=-99.5 required=10.0 tests=ALL_TRUSTED,NO_REAL_NAME X-Spam-Check-By: apache.org Received: from [140.211.11.3] (HELO eris.apache.org) (140.211.11.3) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 19 Apr 2007 09:25:20 -0700 Received: by eris.apache.org (Postfix, from userid 65534) id 56F251A984F; Thu, 19 Apr 2007 09:25:00 -0700 (PDT) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r530474 [3/8] - in /incubator/qpid/trunk/qpid: ./ java/broker/bin/ java/broker/distribution/src/main/assembly/ java/broker/etc/ java/broker/lib/ java/broker/src/main/java/org/apache/qpid/server/ java/broker/src/main/java/org/apache/qpid/ser... Date: Thu, 19 Apr 2007 16:24:45 -0000 To: qpid-commits@incubator.apache.org From: rgreig@apache.org X-Mailer: svnmailer-1.1.0 Message-Id: <20070419162500.56F251A984F@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org Modified: incubator/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/registry/ApplicationRegistry.java URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/registry/ApplicationRegistry.java?view=diff&rev=530474&r1=530473&r2=530474 ============================================================================== --- incubator/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/registry/ApplicationRegistry.java (original) +++ incubator/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/registry/ApplicationRegistry.java Thu Apr 19 09:24:30 2007 @@ -153,7 +153,7 @@ { _logger.error("Error configuring application: " + e, e); //throw new AMQBrokerCreationException(instanceID, "Unable to create Application Registry instance " + instanceID); - throw new RuntimeException("Unable to create Application Registry"); + throw new RuntimeException("Unable to create Application Registry", e); } } else @@ -168,6 +168,12 @@ { virtualHost.close(); } + + // close the rmi registry(if any) started for management + if (getInstance().getManagedObjectRegistry() != null) + { + getInstance().getManagedObjectRegistry().close(); + } } public Configuration getConfiguration() @@ -187,7 +193,7 @@ catch (Exception e) { _logger.error("Unable to instantiate configuration class " + instanceType + " - ensure it has a public default constructor"); - throw new IllegalArgumentException("Unable to instantiate configuration class " + instanceType + " - ensure it has a public default constructor"); + throw new IllegalArgumentException("Unable to instantiate configuration class " + instanceType + " - ensure it has a public default constructor", e); } Configurator.configure(instance); _configuredObjects.put(instanceType, instance); Modified: incubator/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/registry/ConfigurationFileApplicationRegistry.java URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/registry/ConfigurationFileApplicationRegistry.java?view=diff&rev=530474&r1=530473&r2=530474 ============================================================================== --- incubator/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/registry/ConfigurationFileApplicationRegistry.java (original) +++ incubator/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/registry/ConfigurationFileApplicationRegistry.java Thu Apr 19 09:24:30 2007 @@ -42,6 +42,7 @@ import org.apache.qpid.server.security.access.AccessManagerImpl; import org.apache.qpid.server.virtualhost.VirtualHost; import org.apache.qpid.server.virtualhost.VirtualHostRegistry; +import org.apache.qpid.AMQException; public class ConfigurationFileApplicationRegistry extends ApplicationRegistry { @@ -103,6 +104,7 @@ public void initialise() throws Exception { initialiseManagedObjectRegistry(); + _virtualHostRegistry = new VirtualHostRegistry(); _accessManager = new AccessManagerImpl("default", _configuration); @@ -111,7 +113,12 @@ _authenticationManager = new PrincipalDatabaseAuthenticationManager(null, null); + _databaseManager.initialiseManagement(_configuration); + + _managedObjectRegistry.start(); + initialiseVirtualHosts(); + } private void initialiseVirtualHosts() throws Exception @@ -123,7 +130,7 @@ } } - private void initialiseManagedObjectRegistry() + private void initialiseManagedObjectRegistry() throws AMQException { ManagementConfiguration config = getConfiguredObject(ManagementConfiguration.class); if (config.enabled) Modified: incubator/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/AccessManager.java URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/AccessManager.java?view=diff&rev=530474&r1=530473&r2=530474 ============================================================================== --- incubator/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/AccessManager.java (original) +++ incubator/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/AccessManager.java Thu Apr 19 09:24:30 2007 @@ -20,8 +20,13 @@ */ package org.apache.qpid.server.security.access; +import java.security.Principal; + public interface AccessManager { + AccessResult isAuthorized(Accessable accessObject, Principal username, AccessRights.Rights rights); + + @Deprecated AccessResult isAuthorized(Accessable accessObject, String username); String getName(); Modified: incubator/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/AccessManagerImpl.java URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/AccessManagerImpl.java?view=diff&rev=530474&r1=530473&r2=530474 ============================================================================== --- incubator/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/AccessManagerImpl.java (original) +++ incubator/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/AccessManagerImpl.java Thu Apr 19 09:24:30 2007 @@ -23,13 +23,13 @@ import org.apache.commons.configuration.Configuration; import org.apache.commons.configuration.ConfigurationException; import org.apache.qpid.server.registry.ApplicationRegistry; +import org.apache.qpid.server.security.auth.sasl.UsernamePrincipal; import org.apache.qpid.configuration.PropertyUtils; -import org.apache.qpid.configuration.PropertyException; import org.apache.log4j.Logger; import java.util.List; import java.lang.reflect.Method; -import java.lang.reflect.InvocationTargetException; +import java.security.Principal; public class AccessManagerImpl implements AccessManager { @@ -39,8 +39,13 @@ public AccessManagerImpl(String name, Configuration hostConfig) throws ConfigurationException { - String accessClass = hostConfig.getString("security.access.class"); + if (hostConfig == null) + { + _logger.warn("No Configuration specified. Using default access controls for VirtualHost:'" + name + "'"); + return; + } + String accessClass = hostConfig.getString("security.access.class"); if (accessClass == null) { _logger.warn("No access control specified. Using default access controls for VirtualHost:'" + name + "'"); @@ -111,21 +116,35 @@ } catch (Exception e) { - throw new ConfigurationException(e.getCause()); + ConfigurationException ce = new ConfigurationException(e.getMessage(), e.getCause()); + ce.initCause(e); + throw ce; } } } - public AccessResult isAuthorized(Accessable accessObject, String username) { + return isAuthorized(accessObject, new UsernamePrincipal(username), AccessRights.Rights.READ); + } + + public AccessResult isAuthorized(Accessable accessObject, Principal user, AccessRights.Rights rights) + { if (_accessManager == null) { - return ApplicationRegistry.getInstance().getAccessManager().isAuthorized(accessObject, username); + if (ApplicationRegistry.getInstance().getAccessManager() == this) + { + _logger.warn("No Default access manager specified DENYING ALL ACCESS"); + return new AccessResult(this, AccessResult.AccessStatus.REFUSED); + } + else + { + return ApplicationRegistry.getInstance().getAccessManager().isAuthorized(accessObject, user, rights); + } } else { - return _accessManager.isAuthorized(accessObject, username); + return _accessManager.isAuthorized(accessObject, user, rights); } } Modified: incubator/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/AllowAll.java URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/AllowAll.java?view=diff&rev=530474&r1=530473&r2=530474 ============================================================================== --- incubator/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/AllowAll.java (original) +++ incubator/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/AllowAll.java Thu Apr 19 09:24:30 2007 @@ -20,8 +20,15 @@ */ package org.apache.qpid.server.security.access; +import java.security.Principal; + public class AllowAll implements AccessManager { + + public AccessResult isAuthorized(Accessable accessObject, Principal username, AccessRights.Rights rights) + { + return new AccessResult(this, AccessResult.AccessStatus.GRANTED); + } public AccessResult isAuthorized(Accessable accessObject, String username) { Modified: incubator/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/DenyAll.java URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/DenyAll.java?view=diff&rev=530474&r1=530473&r2=530474 ============================================================================== --- incubator/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/DenyAll.java (original) +++ incubator/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/DenyAll.java Thu Apr 19 09:24:30 2007 @@ -20,8 +20,15 @@ */ package org.apache.qpid.server.security.access; +import java.security.Principal; + public class DenyAll implements AccessManager { + public AccessResult isAuthorized(Accessable accessObject, Principal username, AccessRights.Rights rights) + { + return new AccessResult(this, AccessResult.AccessStatus.REFUSED); + } + public AccessResult isAuthorized(Accessable accessObject, String username) { return new AccessResult(this, AccessResult.AccessStatus.REFUSED); Modified: incubator/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/PrincipalDatabaseAccessManager.java URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/PrincipalDatabaseAccessManager.java?view=diff&rev=530474&r1=530473&r2=530474 ============================================================================== --- incubator/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/PrincipalDatabaseAccessManager.java (original) +++ incubator/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/PrincipalDatabaseAccessManager.java Thu Apr 19 09:24:30 2007 @@ -22,8 +22,11 @@ import org.apache.qpid.server.registry.ApplicationRegistry; import org.apache.qpid.server.security.auth.database.PrincipalDatabase; +import org.apache.qpid.server.security.auth.sasl.UsernamePrincipal; import org.apache.log4j.Logger; +import java.security.Principal; + public class PrincipalDatabaseAccessManager implements AccessManager { private static final Logger _logger = Logger.getLogger(PrincipalDatabaseAccessManager.class); @@ -58,15 +61,21 @@ } } + public AccessResult isAuthorized(Accessable accessObject, String username) { + return isAuthorized(accessObject, new UsernamePrincipal(username), AccessRights.Rights.READ); + } + + public AccessResult isAuthorized(Accessable accessObject, Principal username, AccessRights.Rights rights) + { AccessResult result; if (_database == null) { if (_default != null) { - result = _default.isAuthorized(accessObject, username); + result = _default.isAuthorized(accessObject, username, rights); } else { @@ -75,7 +84,15 @@ } else { - result = ((AccessManager) _database).isAuthorized(accessObject, username); + if (!(_database instanceof AccessManager)) + { + _logger.warn("Specified PrincipalDatabase is not an AccessManager so using default AccessManager"); + result = _default.isAuthorized(accessObject, username, rights); + } + else + { + result = ((AccessManager) _database).isAuthorized(accessObject, username, rights); + } } result.addAuthorizer(this); Copied: incubator/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/Base64MD5PasswordFilePrincipalDatabase.java (from r526122, incubator/qpid/branches/M2/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/Base64MD5PasswordFilePrincipalDatabase.java) URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/Base64MD5PasswordFilePrincipalDatabase.java?view=diff&rev=530474&p1=incubator/qpid/branches/M2/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/Base64MD5PasswordFilePrincipalDatabase.java&r1=526122&p2=incubator/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/Base64MD5PasswordFilePrincipalDatabase.java&r2=530474 ============================================================================== --- incubator/qpid/branches/M2/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/Base64MD5PasswordFilePrincipalDatabase.java (original) +++ incubator/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/Base64MD5PasswordFilePrincipalDatabase.java Thu Apr 19 09:24:30 2007 @@ -22,8 +22,11 @@ import org.apache.log4j.Logger; 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.CRAMMD5HashedInitialiser; +import org.apache.qpid.server.security.access.AMQUserManagementMBean; 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; @@ -32,10 +35,17 @@ import java.io.IOException; import java.io.BufferedReader; import java.io.FileReader; +import java.io.UnsupportedEncodingException; +import java.io.PrintStream; import java.util.regex.Pattern; import java.util.Map; import java.util.HashMap; +import java.util.List; +import java.util.LinkedList; +import java.util.concurrent.locks.ReentrantLock; import java.security.Principal; +import java.security.NoSuchAlgorithmException; +import java.security.MessageDigest; /** * Represents a user database where the account information is stored in a simple flat file. @@ -54,6 +64,11 @@ private Map _saslServers; + AMQUserManagementMBean _mbean; + private static final String DEFAULT_ENCODING = "utf-8"; + private Map _users = new HashMap(); + private ReentrantLock _userUpdate = new ReentrantLock(); + public Base64MD5PasswordFilePrincipalDatabase() { _saslServers = new HashMap(); @@ -66,9 +81,20 @@ CRAMMD5HashedInitialiser cram = new CRAMMD5HashedInitialiser(); cram.initialise(this); _saslServers.put(cram.getMechanismName(), cram); + + //fixme The PDs should setup a PD Mangement MBean +// 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 +108,19 @@ throw new FileNotFoundException("Cannot read password file " + f + ". Check permissions."); } + + loadPasswordFile(); } - public void setPassword(Principal principal, PasswordCallback callback) throws IOException, - AccountNotFoundException + /** + * SASL Callback Mechanism - sets the Password in the PasswordCallback based on the value in the PasswordFile + * + * @param principal The Principal to set the password for + * @param callback The PasswordCallback to call setPassword on + * + * @throws AccountNotFoundException If the Principal cannont be found in this Database + */ + public void setPassword(Principal principal, PasswordCallback callback) throws AccountNotFoundException { if (_passwordFile == null) { @@ -95,7 +130,9 @@ { throw new IllegalArgumentException("principal must not be null"); } + char[] pwd = lookupPassword(principal.getName()); + if (pwd != null) { callback.setPassword(pwd); @@ -106,107 +143,484 @@ } } - public boolean verifyPassword(Principal principal, char[] password) throws AccountNotFoundException + /** + * Used to verify that the presented Password is correct. Currently only used by Management Console + * + * @param principal The principal to authenticate + * @param password The password to check + * + * @return true if password is correct + * + * @throws AccountNotFoundException if the principal cannot be found + */ + public boolean verifyPassword(String principal, String password) throws AccountNotFoundException { try { - char[] pwd = lookupPassword(principal.getName()); - return compareCharArray(pwd, password); + char[] pwd = lookupPassword(principal); + 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 getMechanisms() + public boolean updatePassword(Principal principal, String password) throws AccountNotFoundException { - return _saslServers; + User user = _users.get(principal.getName()); + + if (user == null) + { + throw new AccountNotFoundException(principal.getName()); + } + + try + { + + char[] passwd = convertPassword(password); + + try + { + _userUpdate.lock(); + user.setPassword(passwd); + + try + { + savePasswordFile(); + } + catch (IOException e) + { + _logger.error("Unable to save password file, password change for user'" + + principal + "' will revert at restart"); + return false; + } + return true; + } + finally + { + if (_userUpdate.isHeldByCurrentThread()) + { + _userUpdate.unlock(); + } + } + } + catch (UnsupportedEncodingException e) + { + return false; + } } - private boolean compareCharArray(char[] a, char[] b) + private char[] convertPassword(String password) throws UnsupportedEncodingException { - boolean equal = false; - if (a.length == b.length) + byte[] passwdBytes = password.getBytes(DEFAULT_ENCODING); + + char[] passwd = new char[passwdBytes.length]; + + int index = 0; + + for (byte b : passwdBytes) { - equal = true; - int index = 0; - while (equal && index < a.length) + passwd[index++] = (char) b; + } + + return passwd; + } + + public boolean createPrincipal(Principal principal, String password) + { + if (_users.get(principal.getName()) != null) + { + return false; + } + + User user; + try + { + user = new User(principal.getName(), convertPassword(password)); + } + catch (UnsupportedEncodingException e) + { + _logger.warn("Unable to encode password:" + e); + return false; + } + + try + { + _userUpdate.lock(); + _users.put(user.getName(), user); + + try { - equal = a[index] == b[index]; - index++; + savePasswordFile(); + return true; + } + catch (IOException e) + { + return false; + } + + } + finally + { + if (_userUpdate.isHeldByCurrentThread()) + { + _userUpdate.unlock(); } } - return equal; } + public boolean deletePrincipal(Principal principal) throws AccountNotFoundException + { + User user = _users.get(principal.getName()); + + if (user == null) + { + throw new AccountNotFoundException(principal.getName()); + } + + try + { + _userUpdate.lock(); + user.delete(); + + try + { + savePasswordFile(); + } + catch (IOException e) + { + _logger.warn("Unable to remove user '" + user.getName() + "' from password file."); + return false; + } + + _users.remove(user.getName()); + } + finally + { + if (_userUpdate.isHeldByCurrentThread()) + { + _userUpdate.unlock(); + } + } + + return true; + } + + + public Map getMechanisms() + { + return _saslServers; + } + + public List getUsers() + { + return new LinkedList(_users.values()); + } + + public Principal getUser(String username) + { + if (_users.containsKey(username)) + { + return new UsernamePrincipal(username); + } + return null; + } /** * Looks up the password for a specified user in the password file. Note this code is not secure since it * creates strings of passwords. It should be modified to create only char arrays which get nulled out. * - * @param name - * - * @return + * @param name The principal name to lookup * - * @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 { - BufferedReader reader = null; - byte[] passwd = null; try { - reader = new BufferedReader(new FileReader(_passwordFile)); - String line; + _userUpdate.lock(); + _users.clear(); - while ((line = reader.readLine()) != null) + BufferedReader reader = null; + try { - String[] result = _regexp.split(line); - if (result == null || result.length < 2) - { - continue; - } + reader = new BufferedReader(new FileReader(_passwordFile)); + String line; - if (name.equals(result[0])) + while ((line = reader.readLine()) != null) { + String[] result = _regexp.split(line); + if (result == null || result.length < 2 || result[0].startsWith("#")) + { + continue; + } + User user = new User(result); + _logger.info("Created user:" + user); + _users.put(user.getName(), user); + } + } + finally + { + if (reader != null) + { + reader.close(); + } + } + } + finally + { + if (_userUpdate.isHeldByCurrentThread()) + { + _userUpdate.unlock(); + } + } + } - char[] raw = result[1].toCharArray(); + private void savePasswordFile() throws IOException + { + try + { + _userUpdate.lock(); - byte[] encoded = new byte[result[1].length() + 1]; + BufferedReader reader = null; + PrintStream writer = null; + File tmp = new File(_passwordFile.getAbsolutePath() + ".tmp"); + if (tmp.exists()) + { + tmp.delete(); + } + try + { + writer = new PrintStream(tmp); + reader = new BufferedReader(new FileReader(_passwordFile)); + String line; - int index = 0; - for (char c : raw) + while ((line = reader.readLine()) != null) + { + String[] result = _regexp.split(line); + if (result == null || result.length < 2 || result[0].startsWith("#")) { - index++; - encoded[index] = (byte) c; + writer.write(line.getBytes(DEFAULT_ENCODING)); + continue; } - Base64 b64 = new Base64(); - byte[] decoded = b64.decode(encoded); - + User user = _users.get(result[0]); - char[] hashedPassword = new char[decoded.length + 1]; + if (user == null) + { + writer.write(line.getBytes(DEFAULT_ENCODING)); + writer.println(); + } + else if (!user.isDeleted()) + { + if (!user.isModified()) + { + writer.write(line.getBytes(DEFAULT_ENCODING)); + writer.println(); + } + else + { + try + { + byte[] encodedPassword = user.getEncodePassword(); + + writer.write((user.getName() + ":").getBytes(DEFAULT_ENCODING)); + writer.write(encodedPassword); + writer.println(); + + user.saved(); + } + catch (Exception e) + { + _logger.warn("Unable to encode new password reverting to old password."); + writer.write(line.getBytes(DEFAULT_ENCODING)); + writer.println(); + } + } + } + } - index = 0; - for (byte c : decoded) + for (User user : _users.values()) + { + if (user.isModified()) { - index++; - hashedPassword[index] = (char) c; + byte[] encodedPassword; + try + { + encodedPassword = user.getEncodePassword(); + writer.write((user.getName() + ":").getBytes(DEFAULT_ENCODING)); + writer.write(encodedPassword); + writer.println(); + user.saved(); + } + catch (Exception e) + { + _logger.warn("Unable to get Encoded password for user'" + user.getName() + "' password not saved"); + } } + } + } + finally + { + if (reader != null) + { + reader.close(); + } + + if (writer != null) + { + writer.close(); + } - return hashedPassword; + // Swap temp file to main password file. + File old = new File(_passwordFile.getAbsoluteFile() + ".old"); + if (old.exists()) + { + old.delete(); } + _passwordFile.renameTo(old); + tmp.renameTo(_passwordFile); + tmp.delete(); } - return null; } finally { - if (reader != null) + if (_userUpdate.isHeldByCurrentThread()) { - reader.close(); + _userUpdate.unlock(); } } + } + + private class User implements Principal + { + 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); + } + + public String getName() + { + return _name; + } + + public String toString() + { + if (_logger.isDebugEnabled()) + { + return getName() + ((_encodedPassword == null) ? "" : ":" + new String(_encodedPassword)); + } + else + { + return _name; + } + } + + char[] getPassword() + { + return _password; + } + + void setPassword(char[] password) + { + _password = password; + _modified = true; + _encodedPassword = null; + } + + + byte[] getEncodePassword() throws EncoderException, UnsupportedEncodingException, NoSuchAlgorithmException + { + if (_encodedPassword == null) + { + encodePassword(); + } + return _encodedPassword; + } + + private void encodePassword() throws EncoderException, UnsupportedEncodingException, NoSuchAlgorithmException + { + 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; + } + + public void saved() + { + _modified = false; + } + } } Modified: incubator/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/ConfigurationFilePrincipalDatabaseManager.java URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/ConfigurationFilePrincipalDatabaseManager.java?view=diff&rev=530474&r1=530473&r2=530474 ============================================================================== --- incubator/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/ConfigurationFilePrincipalDatabaseManager.java (original) +++ incubator/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/ConfigurationFilePrincipalDatabaseManager.java Thu Apr 19 09:24:30 2007 @@ -1,38 +1,46 @@ /* - * 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 + * 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 * - * 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. + * 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.database; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.lang.reflect.Method; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + import org.apache.commons.configuration.Configuration; import org.apache.commons.configuration.ConfigurationException; + +import org.apache.log4j.Logger; + +import org.apache.qpid.configuration.PropertyUtils; +import org.apache.qpid.configuration.PropertyException; import org.apache.qpid.server.registry.ApplicationRegistry; -import org.apache.qpid.server.security.auth.database.PrincipalDatabaseManager; import org.apache.qpid.server.security.auth.database.PrincipalDatabase; -import org.apache.qpid.configuration.PropertyUtils; -import org.apache.log4j.Logger; +import org.apache.qpid.server.security.auth.database.PrincipalDatabaseManager; +import org.apache.qpid.server.security.access.AMQUserManagementMBean; +import org.apache.qpid.AMQException; -import java.util.Map; -import java.util.List; -import java.util.HashMap; -import java.lang.reflect.Method; -import java.io.FileNotFoundException; +import javax.management.JMException; public class ConfigurationFilePrincipalDatabaseManager implements PrincipalDatabaseManager { @@ -80,18 +88,21 @@ initialisePrincipalDatabase((PrincipalDatabase) o, config, i); String name = databaseNames.get(i); - if (name == null || name.length() == 0) + if ((name == null) || (name.length() == 0)) { throw new Exception("Principal database names must have length greater than or equal to one character"); } + PrincipalDatabase pd = databases.get(name); if (pd != null) { throw new Exception("Duplicate principal database name not provided"); } + _logger.info("Initialised principal database '" + name + "' successfully"); databases.put(name, (PrincipalDatabase) o); } + return databases; } @@ -104,14 +115,16 @@ for (int i = 0; i < argumentNames.size(); i++) { String argName = argumentNames.get(i); - if (argName == null || argName.length() == 0) + if ((argName == null) || (argName.length() == 0)) { throw new ConfigurationException("Argument names must have length >= 1 character"); } + if (Character.isLowerCase(argName.charAt(0))) { argName = Character.toUpperCase(argName.charAt(0)) + argName.substring(1); } + String methodName = "set" + argName; Method method = null; try @@ -125,9 +138,10 @@ if (method == null) { - throw new ConfigurationException("No method " + methodName + " found in class " + principalDatabase.getClass() + - " hence unable to configure principal database. The method must be public and " + - "have a single String argument with a void return type"); + throw new ConfigurationException("No method " + methodName + " found in class " + + principalDatabase.getClass() + + " hence unable to configure principal database. The method must be public and " + + "have a single String argument with a void return type"); } try @@ -136,7 +150,14 @@ } catch (Exception ite) { - throw new ConfigurationException(ite.getCause()); + if (ite instanceof ConfigurationException) + { + throw(ConfigurationException) ite; + } + else + { + throw new ConfigurationException(ite.getMessage(), ite); + } } } } @@ -144,5 +165,72 @@ public Map getDatabases() { return _databases; + } + + public void initialiseManagement(Configuration config) throws ConfigurationException + { + try + { + AMQUserManagementMBean _mbean = new AMQUserManagementMBean(); + + String baseSecurity = "security.jmx"; + List principalDBs = config.getList(baseSecurity + ".principal-database"); + + if (principalDBs.size() == 0) + { + throw new ConfigurationException("No principal-database specified for jmx security(" + baseSecurity + ".principal-database)"); + } + + String databaseName = principalDBs.get(0); + + PrincipalDatabase database = getDatabases().get(databaseName); + + if (database == null) + { + throw new ConfigurationException("Principal-database '" + databaseName + "' not found"); + } + + _mbean.setPrincipalDatabase(database); + + List jmxaccesslist = config.getList(baseSecurity + ".access"); + + if (jmxaccesslist.size() == 0) + { + throw new ConfigurationException("No access control files specified for jmx security(" + baseSecurity + ".access)"); + } + + String jmxaccesssFile = null; + + try + { + jmxaccesssFile = PropertyUtils.replaceProperties(jmxaccesslist.get(0)); + } + catch (PropertyException e) + { + throw new ConfigurationException("Unable to parse access control filename '" + jmxaccesssFile + "'"); + } + + try + { + _mbean.setAccessFile(jmxaccesssFile); + } + catch (IOException e) + { + _logger.warn("Unable to load access file:" + jmxaccesssFile); + } + + try + { + _mbean.register(); + } + catch (AMQException e) + { + _logger.warn("Unable to register user management MBean"); + } + } + catch (JMException e) + { + _logger.warn("User management disabled as unable to create MBean:" + e); + } } } Modified: incubator/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/PlainPasswordFilePrincipalDatabase.java URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/PlainPasswordFilePrincipalDatabase.java?view=diff&rev=530474&r1=530473&r2=530474 ============================================================================== --- incubator/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/PlainPasswordFilePrincipalDatabase.java (original) +++ incubator/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/PlainPasswordFilePrincipalDatabase.java Thu Apr 19 09:24:30 2007 @@ -21,8 +21,8 @@ package org.apache.qpid.server.security.auth.database; import org.apache.log4j.Logger; -import org.apache.qpid.server.security.auth.database.PrincipalDatabase; 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.amqplain.AmqPlainInitialiser; import org.apache.qpid.server.security.auth.sasl.crammd5.CRAMMD5Initialiser; import org.apache.qpid.server.security.auth.sasl.plain.PlainInitialiser; @@ -34,9 +34,11 @@ 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; +import java.util.List; import java.security.Principal; /** @@ -119,21 +121,103 @@ } } + public boolean verifyPassword(String principal, String password) throws AccountNotFoundException + { + try + { + char[] pwd = lookupPassword(principal); + + return compareCharArray(pwd, convertPassword(password)); + } + catch (IOException e) + { + return false; + } + } + + 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) + { + return false; // updates denied + } + + public boolean deletePrincipal(Principal principal) throws AccountNotFoundException + { + return false; // updates denied + } + public Map getMechanisms() { return _saslServers; } + public List getUsers() + { + return null; //todo + } + + public Principal getUser(String username) + { + try + { + if (lookupPassword(username) != null) + { + return new UsernamePrincipal(username); + } + } + catch (IOException e) + { + //fall through to null return + } + return null; + } + + private boolean compareCharArray(char[] a, char[] b) + { + boolean equal = false; + if (a.length == b.length) + { + equal = true; + int index = 0; + while (equal && index < a.length) + { + equal = a[index] == b[index]; + index++; + } + } + return equal; + } + /** * Looks up the password for a specified user in the password file. Note this code is not 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 name of the principal to lookup * - * @return + * @return char[] of the password * - * @throws java.io.IOException + * @throws java.io.IOException whilst accessing the file */ private char[] lookupPassword(String name) throws IOException { Modified: incubator/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/PlainPasswordVhostFilePrincipalDatabase.java URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/PlainPasswordVhostFilePrincipalDatabase.java?view=diff&rev=530474&r1=530473&r2=530474 ============================================================================== --- incubator/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/PlainPasswordVhostFilePrincipalDatabase.java (original) +++ incubator/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/PlainPasswordVhostFilePrincipalDatabase.java Thu Apr 19 09:24:30 2007 @@ -20,26 +20,17 @@ */ package org.apache.qpid.server.security.auth.database; -import org.apache.qpid.server.security.auth.database.PrincipalDatabase; -import org.apache.qpid.server.security.auth.sasl.AuthenticationProviderInitialiser; -import org.apache.qpid.server.security.auth.sasl.crammd5.CRAMMD5Initialiser; -import org.apache.qpid.server.security.auth.sasl.plain.PlainInitialiser; import org.apache.qpid.server.security.access.AccessManager; import org.apache.qpid.server.security.access.AccessResult; import org.apache.qpid.server.security.access.Accessable; +import org.apache.qpid.server.security.access.AccessRights; +import org.apache.qpid.server.security.auth.sasl.UsernamePrincipal; import org.apache.qpid.server.virtualhost.VirtualHost; import org.apache.log4j.Logger; -import javax.security.auth.callback.PasswordCallback; -import javax.security.auth.login.AccountNotFoundException; -import java.io.File; -import java.io.FileNotFoundException; import java.io.IOException; import java.io.BufferedReader; import java.io.FileReader; -import java.util.regex.Pattern; -import java.util.Map; -import java.util.HashMap; import java.security.Principal; /** @@ -103,9 +94,15 @@ public AccessResult isAuthorized(Accessable accessObject, String username) { + return isAuthorized(accessObject, new UsernamePrincipal(username), AccessRights.Rights.READ); + } + + public AccessResult isAuthorized(Accessable accessObject, Principal user, AccessRights.Rights rights) + { + if (accessObject instanceof VirtualHost) { - String[] hosts = lookupVirtualHost(username); + String[] hosts = lookupVirtualHost(user.getName()); if (hosts != null) { @@ -126,4 +123,5 @@ { return "PlainPasswordVhostFile"; } + } Modified: incubator/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/PrincipalDatabase.java URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/PrincipalDatabase.java?view=diff&rev=530474&r1=530473&r2=530474 ============================================================================== --- incubator/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/PrincipalDatabase.java (original) +++ incubator/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/PrincipalDatabase.java Thu Apr 19 09:24:30 2007 @@ -23,8 +23,10 @@ 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; +import java.util.List; import javax.security.auth.callback.PasswordCallback; import javax.security.auth.login.AccountNotFoundException; @@ -46,5 +48,53 @@ void setPassword(Principal principal, PasswordCallback callback) throws IOException, AccountNotFoundException; + /** + * Used to verify that the presented Password is correct. Currently only used by Management Console + * @param principal The principal to authenticate + * @param password The password to check + * @return true if password is correct + * @throws AccountNotFoundException if the principal cannot be found + */ + boolean verifyPassword(String principal, String password) + throws AccountNotFoundException; + + /** + * Update(Change) the password for the given principal + * @param principal Who's password is to be changed + * @param password The new password to use + * @return True if change was successful + * @throws AccountNotFoundException If the given principal doesn't exist in the Database + */ + boolean updatePassword(Principal principal, String password) + throws AccountNotFoundException; + + /** + * Create a new principal in the database + * @param principal The principal to create + * @param password The password to set for the principal + * @return True on a successful creation + */ + boolean createPrincipal(Principal principal, String password); + + /** + * Delete a principal + * @param principal The principal to delete + * @return True on a successful creation + * @throws AccountNotFoundException If the given principal doesn't exist in the Database + */ + boolean deletePrincipal(Principal principal) + throws AccountNotFoundException; + + /** + * Get the principal from the database with the given username + * @param username of the principal to lookup + * @return The Principal object for the given username or null if not found. + */ + Principal getUser(String username); + + public Map getMechanisms(); + + + List getUsers(); } Modified: incubator/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/PrincipalDatabaseManager.java URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/PrincipalDatabaseManager.java?view=diff&rev=530474&r1=530473&r2=530474 ============================================================================== --- incubator/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/PrincipalDatabaseManager.java (original) +++ incubator/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/PrincipalDatabaseManager.java Thu Apr 19 09:24:30 2007 @@ -21,10 +21,14 @@ package org.apache.qpid.server.security.auth.database; import org.apache.qpid.server.security.auth.database.PrincipalDatabase; +import org.apache.commons.configuration.Configuration; +import org.apache.commons.configuration.ConfigurationException; import java.util.Map; public interface PrincipalDatabaseManager { public Map getDatabases(); + + public void initialiseManagement(Configuration config) throws ConfigurationException; } Modified: incubator/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/PropertiesPrincipalDatabase.java URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/PropertiesPrincipalDatabase.java?view=diff&rev=530474&r1=530473&r2=530474 ============================================================================== --- incubator/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/PropertiesPrincipalDatabase.java (original) +++ incubator/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/PropertiesPrincipalDatabase.java Thu Apr 19 09:24:30 2007 @@ -21,6 +21,7 @@ package org.apache.qpid.server.security.auth.database; 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.CRAMMD5Initialiser; import org.apache.qpid.server.security.auth.sasl.plain.PlainInitialiser; @@ -29,8 +30,10 @@ import java.util.Properties; import java.util.Map; import java.util.HashMap; +import java.util.List; import java.security.Principal; import java.io.IOException; +import java.io.UnsupportedEncodingException; public class PropertiesPrincipalDatabase implements PrincipalDatabase { @@ -76,8 +79,87 @@ } } + public boolean verifyPassword(String principal, String password) throws AccountNotFoundException + { + char[] pwd = _users.getProperty(principal).toCharArray(); + + 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) + { + return false; // updates denied + } + + public boolean deletePrincipal(Principal principal) throws AccountNotFoundException + { + return false; // updates denied + } + + private boolean compareCharArray(char[] a, char[] b) + { + boolean equal = false; + if (a.length == b.length) + { + equal = true; + int index = 0; + while (equal && index < a.length) + { + equal = a[index] == b[index]; + index++; + } + } + 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 getMechanisms() { return _saslServers; + } + + public List getUsers() + { + return null; //todo + } + + public Principal getUser(String username) + { + if (_users.getProperty(username) != null) + { + return new UsernamePrincipal(username); + } + else + { + return null; + } } } Modified: incubator/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/PropertiesPrincipalDatabaseManager.java URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/PropertiesPrincipalDatabaseManager.java?view=diff&rev=530474&r1=530473&r2=530474 ============================================================================== --- incubator/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/PropertiesPrincipalDatabaseManager.java (original) +++ incubator/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/PropertiesPrincipalDatabaseManager.java Thu Apr 19 09:24:30 2007 @@ -20,6 +20,8 @@ */ package org.apache.qpid.server.security.auth.database; +import org.apache.commons.configuration.Configuration; + import java.util.Map; import java.util.Properties; import java.util.HashMap; @@ -37,5 +39,10 @@ public Map getDatabases() { return _databases; + } + + public void initialiseManagement(Configuration config) + { + //todo } } Modified: incubator/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/PrincipalDatabaseAuthenticationManager.java URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/PrincipalDatabaseAuthenticationManager.java?view=diff&rev=530474&r1=530473&r2=530474 ============================================================================== --- incubator/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/PrincipalDatabaseAuthenticationManager.java (original) +++ incubator/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/PrincipalDatabaseAuthenticationManager.java Thu Apr 19 09:24:30 2007 @@ -71,7 +71,7 @@ Map> providerMap = new TreeMap>(); - if (name == null) + if (name == null || hostConfig == null) { initialiseAuthenticationMechanisms(providerMap, ApplicationRegistry.getInstance().getDatabaseManager().getDatabases()); } @@ -108,11 +108,15 @@ if (providerMap.size() > 0) { - Security.addProvider(new JCAProvider(providerMap)); + // Ensure we are used before the defaults + if (Security.insertProviderAt(new JCAProvider(providerMap), 1) == -1) + { + _logger.warn("Unable to set order of providers."); + } } else { - _logger.warn("No SASL providers availble."); + _logger.warn("No additional SASL providers registered."); } } @@ -148,21 +152,20 @@ { if (database == null || database.getMechanisms().size() == 0) { - _logger.warn(""); + _logger.warn("No Database or no mechanisms to initialise authentication"); return; } - for (AuthenticationProviderInitialiser mechanism : database.getMechanisms().values()) + for (Map.Entry mechanism : database.getMechanisms().entrySet()) { - initialiseAuthenticationMechanism(mechanism, providerMap); + initialiseAuthenticationMechanism(mechanism.getKey(), mechanism.getValue(), providerMap); } } - private void initialiseAuthenticationMechanism(AuthenticationProviderInitialiser initialiser, + private void initialiseAuthenticationMechanism(String mechanism, AuthenticationProviderInitialiser initialiser, Map> providerMap) throws Exception { - String mechanism = initialiser.getMechanismName(); if (_mechanisms == null) { _mechanisms = mechanism; Modified: incubator/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/JCAProvider.java URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/JCAProvider.java?view=diff&rev=530474&r1=530473&r2=530474 ============================================================================== --- incubator/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/JCAProvider.java (original) +++ incubator/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/JCAProvider.java Thu Apr 19 09:24:30 2007 @@ -33,7 +33,7 @@ super("AMQSASLProvider", 1.0, "A JCA provider that registers all " + "AMQ SASL providers that want to be registered"); register(providerMap); - Security.addProvider(this); + //Security.addProvider(this); } private void register(Map> providerMap) Modified: incubator/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/UsernamePasswordInitialiser.java URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/UsernamePasswordInitialiser.java?view=diff&rev=530474&r1=530473&r2=530474 ============================================================================== --- incubator/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/UsernamePasswordInitialiser.java (original) +++ incubator/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/UsernamePasswordInitialiser.java Thu Apr 19 09:24:30 2007 @@ -7,9 +7,9 @@ * 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 @@ -33,14 +33,16 @@ import javax.security.sasl.AuthorizeCallback; import org.apache.commons.configuration.Configuration; + import org.apache.log4j.Logger; + import org.apache.qpid.server.security.auth.database.PrincipalDatabase; import org.apache.qpid.server.security.auth.sasl.AuthenticationProviderInitialiser; import org.apache.qpid.server.security.auth.sasl.UsernamePrincipal; public abstract class UsernamePasswordInitialiser implements AuthenticationProviderInitialiser { - protected static final Logger _logger = Logger.getLogger(UsernamePasswordInitialiser.class); + protected static final Logger _logger = Logger.getLogger(UsernamePasswordInitialiser.class); private ServerCallbackHandler _callbackHandler; @@ -72,7 +74,9 @@ { // very annoyingly the callback handler does not throw anything more appropriate than // IOException - throw new IOException("Error looking up user " + e); + IOException ioe = new IOException("Error looking up user " + e); + ioe.initCause(e); + throw ioe; } } else if (callback instanceof AuthorizeCallback) @@ -88,7 +92,7 @@ } public void initialise(String baseConfigPath, Configuration configuration, - Map principalDatabases) throws Exception + Map principalDatabases) throws Exception { String principalDatabaseName = configuration.getString(baseConfigPath + ".principal-database"); PrincipalDatabase db = principalDatabases.get(principalDatabaseName); @@ -102,6 +106,7 @@ { throw new NullPointerException("Cannot initialise with a null Principal database."); } + _callbackHandler = new ServerCallbackHandler(db); } Modified: incubator/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/UsernamePrincipal.java URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/UsernamePrincipal.java?view=diff&rev=530474&r1=530473&r2=530474 ============================================================================== --- incubator/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/UsernamePrincipal.java (original) +++ incubator/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/UsernamePrincipal.java Thu Apr 19 09:24:30 2007 @@ -22,10 +22,7 @@ import java.security.Principal; -/** - * A principal that is just a wrapper for a simple username. - * - */ +/** A principal that is just a wrapper for a simple username. */ public class UsernamePrincipal implements Principal { private String _name; @@ -36,6 +33,11 @@ } public String getName() + { + return _name; + } + + public String toString() { return _name; } Modified: incubator/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/plain/PlainSaslServerFactory.java URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/plain/PlainSaslServerFactory.java?view=diff&rev=530474&r1=530473&r2=530474 ============================================================================== --- incubator/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/plain/PlainSaslServerFactory.java (original) +++ incubator/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/plain/PlainSaslServerFactory.java Thu Apr 19 09:24:30 2007 @@ -29,7 +29,7 @@ import javax.security.sasl.SaslServerFactory; public class PlainSaslServerFactory implements SaslServerFactory -{ +{ public SaslServer createSaslServer(String mechanism, String protocol, String serverName, Map props, CallbackHandler cbh) throws SaslException { Modified: incubator/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/txn/CleanupMessageOperation.java URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/txn/CleanupMessageOperation.java?view=diff&rev=530474&r1=530473&r2=530474 ============================================================================== --- incubator/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/txn/CleanupMessageOperation.java (original) +++ incubator/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/txn/CleanupMessageOperation.java Thu Apr 19 09:24:30 2007 @@ -56,18 +56,7 @@ public void commit(StoreContext context) { - //The routers reference can now be released. This is done - //here to ensure that it happens after the queues that - //enqueue it have incremented their counts (which as a - //memory only operation is done in the commit phase). - try - { - _msg.decrementReference(context); - } - catch (AMQException e) - { - _log.error("On commiting transaction, failed to cleanup unused message: " + e, e); - } + try { _msg.checkDeliveredToConsumer(); Modified: incubator/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/txn/LocalTransactionalContext.java URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/txn/LocalTransactionalContext.java?view=diff&rev=530474&r1=530473&r2=530474 ============================================================================== --- incubator/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/txn/LocalTransactionalContext.java (original) +++ incubator/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/txn/LocalTransactionalContext.java Thu Apr 19 09:24:30 2007 @@ -89,6 +89,12 @@ public void rollback() throws AMQException { _txnBuffer.rollback(_storeContext); + // Hack to deal with uncommitted non-transactional writes + if(_messageStore.inTran(_storeContext)) + { + _messageStore.abortTran(_storeContext); + _inTran = false; + } _postCommitDeliveryList.clear(); } @@ -103,6 +109,7 @@ // message.incrementReference(); _postCommitDeliveryList.add(new DeliveryDetails(message, queue, deliverFirst)); _messageDelivered = true; + _txnBuffer.enlist(new CleanupMessageOperation(message, _returnMessages)); /*_txnBuffer.enlist(new DeliverMessageOperation(message, queue)); if (_log.isDebugEnabled()) { @@ -111,7 +118,7 @@ } message.incrementReference(); _messageDelivered = true; - _txnBuffer.enlist(new CleanupMessageOperation(message, _returnMessages)); + */ } @@ -195,6 +202,7 @@ { _txnBuffer.enlist(new StoreMessageOperation(_messageStore)); } + //fixme fail commit here ... QPID-440 try { _txnBuffer.commit(_storeContext); Modified: incubator/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/txn/TxnBuffer.java URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/txn/TxnBuffer.java?view=diff&rev=530474&r1=530473&r2=530474 ============================================================================== --- incubator/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/txn/TxnBuffer.java (original) +++ incubator/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/txn/TxnBuffer.java Thu Apr 19 09:24:30 2007 @@ -41,7 +41,7 @@ { if (_log.isDebugEnabled()) { - _log.debug("Committing " + _ops.size() + " ops to commit.:" + _ops.toArray()); + _log.debug("Committing " + _ops.size() + " ops to commit.:" + _ops); } if (prepare(context)) Modified: incubator/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHost.java URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHost.java?view=diff&rev=530474&r1=530473&r2=530474 ============================================================================== --- incubator/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHost.java (original) +++ incubator/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHost.java Thu Apr 19 09:24:30 2007 @@ -181,7 +181,7 @@ catch (Exception e) { _logger.error("Unable to instantiate configuration class " + instanceType + " - ensure it has a public default constructor"); - throw new IllegalArgumentException("Unable to instantiate configuration class " + instanceType + " - ensure it has a public default constructor"); + throw new IllegalArgumentException("Unable to instantiate configuration class " + instanceType + " - ensure it has a public default constructor", e); } Configurator.configure(instance); Modified: incubator/qpid/trunk/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/AMQQueueAlertTest.java URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/AMQQueueAlertTest.java?view=diff&rev=530474&r1=530473&r2=530474 ============================================================================== --- incubator/qpid/trunk/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/AMQQueueAlertTest.java (original) +++ incubator/qpid/trunk/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/AMQQueueAlertTest.java Thu Apr 19 09:24:30 2007 @@ -106,6 +106,8 @@ /** * Tests if Queue Depth alert is thrown when queue depth reaches the threshold value * + * Based on FT402 subbmitted by client + * * @throws Exception */ public void testQueueDepthAlertNoSubscriber() throws Exception Modified: incubator/qpid/trunk/qpid/java/client/example/src/main/java/org/apache/qpid/example/publisher/FileMessageDispatcher.java URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/java/client/example/src/main/java/org/apache/qpid/example/publisher/FileMessageDispatcher.java?view=diff&rev=530474&r1=530473&r2=530474 ============================================================================== --- incubator/qpid/trunk/qpid/java/client/example/src/main/java/org/apache/qpid/example/publisher/FileMessageDispatcher.java (original) +++ incubator/qpid/trunk/qpid/java/client/example/src/main/java/org/apache/qpid/example/publisher/FileMessageDispatcher.java Thu Apr 19 09:24:30 2007 @@ -1,4 +1,5 @@ /* + * * 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 @@ -6,33 +7,35 @@ * 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.example.publisher; -import org.apache.log4j.Logger; - import java.io.File; +import javax.jms.JMSException; + +import org.apache.log4j.Logger; + import org.apache.qpid.example.shared.FileUtils; import org.apache.qpid.example.shared.Statics; -import javax.jms.JMSException; - /** * Class that sends message files to the Publisher to distribute * using files as input * Must set properties for host in properties file or uses in vm broker */ -public class FileMessageDispatcher { +public class FileMessageDispatcher +{ protected static final Logger _logger = Logger.getLogger(FileMessageDispatcher.class); @@ -48,30 +51,30 @@ public static void main(String[] args) { - //Check command line args ok - must provide a path or file for us to dispatch + // Check command line args ok - must provide a path or file for us to dispatch if (args.length == 0) { - System.err.println("Usage: FileMessageDispatcher " + ""); + System.out.println("Usage: FileMessageDispatcher " + ""); } else { try { - //publish message(s) from file(s) to configured queue + // publish message(s) from file(s) to configured queue publish(args[0]); - //Move payload file(s) to archive location as no error + // Move payload file(s) to archive location as no error FileUtils.moveFileToNewDir(args[0], System.getProperties().getProperty(Statics.ARCHIVE_PATH)); } - catch(Exception e) + catch (Exception e) { - //log error and exit + // log error and exit _logger.error("Error trying to dispatch message: " + e); System.exit(1); } finally { - //clean up before exiting + // clean up before exiting if (getPublisher() != null) { getPublisher().cleanup(); @@ -98,10 +101,10 @@ File tempFile = new File(path); if (tempFile.isDirectory()) { - //while more files in dir publish them + // while more files in dir publish them File[] files = tempFile.listFiles(); - if (files == null || files.length == 0) + if ((files == null) || (files.length == 0)) { _logger.info("FileMessageDispatcher - No files to publish in input directory: " + tempFile); } @@ -109,10 +112,10 @@ { for (File file : files) { - //Create message factory passing in payload path + // Create message factory passing in payload path FileMessageFactory factory = new FileMessageFactory(getPublisher().getSession(), file.toString()); - //Send the message generated from the payload using the _publisher + // Send the message generated from the payload using the _publisher getPublisher().sendMessage(factory.createEventMessage()); } @@ -120,11 +123,11 @@ } else { - //handle a single file - //Create message factory passing in payload path - FileMessageFactory factory = new FileMessageFactory(getPublisher().getSession(),tempFile.toString()); + // handle a single file + // Create message factory passing in payload path + FileMessageFactory factory = new FileMessageFactory(getPublisher().getSession(), tempFile.toString()); - //Send the message generated from the payload using the _publisher + // Send the message generated from the payload using the _publisher getPublisher().sendMessage(factory.createEventMessage()); } } @@ -145,15 +148,15 @@ */ private static Publisher getPublisher() { - if (_publisher != null) - { - return _publisher; - } + if (_publisher != null) + { + return _publisher; + } - //Create a _publisher - _publisher = new Publisher(); + // Create a _publisher + _publisher = new Publisher(); - return _publisher; + return _publisher; } } Modified: incubator/qpid/trunk/qpid/java/client/example/src/main/java/org/apache/qpid/example/publisher/FileMessageFactory.java URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/java/client/example/src/main/java/org/apache/qpid/example/publisher/FileMessageFactory.java?view=diff&rev=530474&r1=530473&r2=530474 ============================================================================== --- incubator/qpid/trunk/qpid/java/client/example/src/main/java/org/apache/qpid/example/publisher/FileMessageFactory.java (original) +++ incubator/qpid/trunk/qpid/java/client/example/src/main/java/org/apache/qpid/example/publisher/FileMessageFactory.java Thu Apr 19 09:24:30 2007 @@ -47,7 +47,9 @@ } catch (IOException e) { - throw new MessageFactoryException(e.toString()); + MessageFactoryException mfe = new MessageFactoryException(e.toString()); + mfe.initCause(e); + throw mfe; } } Modified: incubator/qpid/trunk/qpid/java/client/example/src/main/java/org/apache/qpid/example/shared/InitialContextHelper.java URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/java/client/example/src/main/java/org/apache/qpid/example/shared/InitialContextHelper.java?view=diff&rev=530474&r1=530473&r2=530474 ============================================================================== --- incubator/qpid/trunk/qpid/java/client/example/src/main/java/org/apache/qpid/example/shared/InitialContextHelper.java (original) +++ incubator/qpid/trunk/qpid/java/client/example/src/main/java/org/apache/qpid/example/shared/InitialContextHelper.java Thu Apr 19 09:24:30 2007 @@ -59,11 +59,11 @@ } catch (IOException e) { - throw new ContextException(e.toString()); + throw new ContextException(e.toString(), e); } catch (NamingException n) { - throw new ContextException(n.toString()); + throw new ContextException(n.toString(), n); } }