summaryrefslogtreecommitdiff
path: root/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/Base64MD5PasswordFilePrincipalDatabase.java
diff options
context:
space:
mode:
Diffstat (limited to 'qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/Base64MD5PasswordFilePrincipalDatabase.java')
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/Base64MD5PasswordFilePrincipalDatabase.java475
1 files changed, 12 insertions, 463 deletions
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/Base64MD5PasswordFilePrincipalDatabase.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/Base64MD5PasswordFilePrincipalDatabase.java
index 5a92b33e43..63eb768035 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/Base64MD5PasswordFilePrincipalDatabase.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/Base64MD5PasswordFilePrincipalDatabase.java
@@ -21,29 +21,12 @@
package org.apache.qpid.server.security.auth.database;
import org.apache.log4j.Logger;
-import org.apache.qpid.server.security.auth.management.AMQUserManagementMBean;
-import org.apache.qpid.server.security.auth.sasl.AuthenticationProviderInitialiser;
-import org.apache.qpid.server.security.auth.sasl.UsernamePrincipal;
-import org.apache.qpid.server.security.auth.sasl.crammd5.CRAMMD5HexInitialiser;
+
import org.apache.qpid.server.security.auth.sasl.crammd5.CRAMMD5HashedInitialiser;
-import org.apache.qpid.util.FileUtils;
+import org.apache.qpid.server.security.auth.sasl.crammd5.CRAMMD5HexInitialiser;
-import javax.security.auth.callback.PasswordCallback;
import javax.security.auth.login.AccountNotFoundException;
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.FileReader;
-import java.io.IOException;
-import java.io.PrintStream;
import java.security.Principal;
-import java.util.HashMap;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.Random;
-import java.util.concurrent.locks.ReentrantLock;
-import java.util.regex.Pattern;
/**
* Represents a user database where the account information is stored in a simple flat file.
@@ -52,100 +35,19 @@ import java.util.regex.Pattern;
*
* where a carriage return separates each username/password pair. Passwords are assumed to be in plain text.
*/
-public class Base64MD5PasswordFilePrincipalDatabase implements PrincipalDatabase
+public class Base64MD5PasswordFilePrincipalDatabase extends AbstractPasswordFilePrincipalDatabase<HashedUser>
{
- private static final Logger _logger = Logger.getLogger(Base64MD5PasswordFilePrincipalDatabase.class);
-
- private File _passwordFile;
-
- private Pattern _regexp = Pattern.compile(":");
-
- private Map<String, AuthenticationProviderInitialiser> _saslServers;
-
- AMQUserManagementMBean _mbean;
- public static final String DEFAULT_ENCODING = "utf-8";
- private Map<String, HashedUser> _users = new HashMap<String, HashedUser>();
- private ReentrantLock _userUpdate = new ReentrantLock();
+ private final Logger _logger = Logger.getLogger(Base64MD5PasswordFilePrincipalDatabase.class);
public Base64MD5PasswordFilePrincipalDatabase()
{
- _saslServers = new HashMap<String, AuthenticationProviderInitialiser>();
-
/**
* Create Authenticators for MD5 Password file.
*/
+ super(new CRAMMD5HashedInitialiser(), new CRAMMD5HexInitialiser());
- // Accept Plain incomming and hash it for comparison to the file.
- CRAMMD5HashedInitialiser cram = new CRAMMD5HashedInitialiser();
- cram.initialise(this);
- _saslServers.put(cram.getMechanismName(), cram);
-
- //Add the Hex initialiser
- CRAMMD5HexInitialiser cramHex = new CRAMMD5HexInitialiser();
- cramHex.initialise(this);
- _saslServers.put(cramHex.getMechanismName(), cramHex);
-
- //fixme The PDs should setup a PD Mangement MBean
-// try
-// {
-// _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 IOException
- {
- File f = new File(passwordFile);
- _logger.info("PasswordFilePrincipalDatabase using file " + f.getAbsolutePath());
- _passwordFile = f;
- if (!f.exists())
- {
- throw new FileNotFoundException("Cannot find password file " + f);
- }
- if (!f.canRead())
- {
- throw new FileNotFoundException("Cannot read password file " + f +
- ". Check permissions.");
- }
-
- loadPasswordFile();
}
- /**
- * SASL Callback Mechanism - sets the Password in the PasswordCallback based on the value in the PasswordFile
- * If you want to change the password for a user, use updatePassword instead.
- *
- * @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)
- {
- throw new AccountNotFoundException("Unable to locate principal since no password file was specified during initialisation");
- }
- if (principal == null)
- {
- throw new IllegalArgumentException("principal must not be null");
- }
-
- char[] pwd = lookupPassword(principal.getName());
-
- if (pwd != null)
- {
- callback.setPassword(pwd);
- }
- else
- {
- throw new AccountNotFoundException("No account found for principal " + principal);
- }
- }
/**
* Used to verify that the presented Password is correct. Currently only used by Management Console
@@ -180,7 +82,7 @@ public class Base64MD5PasswordFilePrincipalDatabase implements PrincipalDatabase
}
catch (Exception e1)
{
- _logger.warn("Unable to hash password for user '" + principal + "' for comparison");
+ getLogger().warn("Unable to hash password for user '" + principal + "' for comparison");
return false;
}
@@ -194,374 +96,21 @@ public class Base64MD5PasswordFilePrincipalDatabase implements PrincipalDatabase
return compareCharArray(pwd, hashedPassword);
}
-
- 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;
- }
- /**
- * Changes the password for the specified user
- *
- * @param principal to change the password for
- * @param password plaintext password to set the password too
- */
- public boolean updatePassword(Principal principal, char[] password) throws AccountNotFoundException
+ protected HashedUser createUserFromPassword(Principal principal, char[] passwd)
{
- HashedUser user = _users.get(principal.getName());
-
- if (user == null)
- {
- throw new AccountNotFoundException(principal.getName());
- }
-
- try
- {
- try
- {
- _userUpdate.lock();
- char[] orig = user.getPassword();
- user.setPassword(password,false);
-
- try
- {
- savePasswordFile();
- }
- catch (IOException e)
- {
- _logger.error("Unable to save password file, password change for user'"
- + principal + "' will revert at restart");
- //revert the password change
- user.setPassword(orig,true);
- return false;
- }
- return true;
- }
- finally
- {
- _userUpdate.unlock();
- }
- }
- catch (Exception e)
- {
- return false;
- }
+ return new HashedUser(principal.getName(), passwd);
}
- public boolean createPrincipal(Principal principal, char[] password)
- {
- if (_users.get(principal.getName()) != null)
- {
- return false;
- }
- HashedUser user;
- try
- {
- user = new HashedUser(principal.getName(), password);
- }
- catch (Exception e1)
- {
- _logger.warn("Unable to create new user '" + principal.getName() + "'");
- return false;
- }
-
-
- try
- {
- _userUpdate.lock();
- _users.put(user.getName(), user);
-
- try
- {
- savePasswordFile();
- return true;
- }
- catch (IOException e)
- {
- //remove the use on failure.
- _users.remove(user.getName());
- return false;
- }
- }
- finally
- {
- _userUpdate.unlock();
- }
- }
-
- public boolean deletePrincipal(Principal principal) throws AccountNotFoundException
- {
- HashedUser 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
- {
- _userUpdate.unlock();
- }
-
- return true;
- }
-
- public Map<String, AuthenticationProviderInitialiser> getMechanisms()
- {
- return _saslServers;
- }
-
- public List<Principal> getUsers()
- {
- return new LinkedList<Principal>(_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 <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 The principal name to lookup
- *
- * @return a char[] for use in SASL.
- */
- private char[] lookupPassword(String name)
+ protected HashedUser createUserFromFileData(String[] result)
{
- HashedUser user = _users.get(name);
- if (user == null)
- {
- return null;
- }
- else
- {
- return user.getPassword();
- }
- }
-
- private void loadPasswordFile() throws IOException
- {
- try
- {
- _userUpdate.lock();
- _users.clear();
-
- BufferedReader reader = null;
- try
- {
- reader = new BufferedReader(new FileReader(_passwordFile));
- String line;
-
- while ((line = reader.readLine()) != null)
- {
- String[] result = _regexp.split(line);
- if (result == null || result.length < 2 || result[0].startsWith("#"))
- {
- continue;
- }
-
- HashedUser user = new HashedUser(result);
- _logger.info("Created user:" + user);
- _users.put(user.getName(), user);
- }
- }
- finally
- {
- if (reader != null)
- {
- reader.close();
- }
- }
- }
- finally
- {
- _userUpdate.unlock();
- }
- }
-
- private void savePasswordFile() throws IOException
- {
- try
- {
- _userUpdate.lock();
-
- BufferedReader reader = null;
- PrintStream writer = null;
-
- Random r = new Random();
- File tmp;
- do
- {
- tmp = new File(_passwordFile.getPath() + r.nextInt() + ".tmp");
- }
- while(tmp.exists());
-
- tmp.deleteOnExit();
-
- try
- {
- writer = new PrintStream(tmp);
- reader = new BufferedReader(new FileReader(_passwordFile));
- String line;
-
- 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));
- writer.println();
- continue;
- }
-
- HashedUser user = _users.get(result[0]);
-
- 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.getEncodedPassword();
-
- 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();
- }
- }
- }
- }
-
- for (HashedUser user : _users.values())
- {
- if (user.isModified())
- {
- byte[] encodedPassword;
- try
- {
- encodedPassword = user.getEncodedPassword();
- 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");
- }
- }
- }
- }
- catch(IOException e)
- {
- _logger.error("Unable to create the new password file: " + e);
- throw new IOException("Unable to create the new password file" + e);
- }
- finally
- {
- if (reader != null)
- {
- reader.close();
- }
-
- if (writer != null)
- {
- writer.close();
- }
- }
-
- // Swap temp file to main password file.
- File old = new File(_passwordFile.getAbsoluteFile() + ".old");
- if (old.exists())
- {
- old.delete();
- }
-
- if(!_passwordFile.renameTo(old))
- {
- //unable to rename the existing file to the backup name
- _logger.error("Could not backup the existing password file");
- throw new IOException("Could not backup the existing password file");
- }
-
- if(!tmp.renameTo(_passwordFile))
- {
- //failed to rename the new file to the required filename
-
- if(!old.renameTo(_passwordFile))
- {
- //unable to return the backup to required filename
- _logger.error("Could not rename the new password file into place, and unable to restore original file");
- throw new IOException("Could not rename the new password file into place, and unable to restore original file");
- }
-
- _logger.error("Could not rename the new password file into place");
- throw new IOException("Could not rename the new password file into place");
- }
- }
- finally
- {
- _userUpdate.unlock();
- }
+ return new HashedUser(result);
}
- public void reload() throws IOException
+ protected Logger getLogger()
{
- loadPasswordFile();
+ return _logger;
}
}