diff --git a/projects/samskivert/src/java/com/samskivert/servlet/user/Authenticator.java b/projects/samskivert/src/java/com/samskivert/servlet/user/Authenticator.java
index 39d1bdad..979bb750 100644
--- a/projects/samskivert/src/java/com/samskivert/servlet/user/Authenticator.java
+++ b/projects/samskivert/src/java/com/samskivert/servlet/user/Authenticator.java
@@ -44,6 +44,6 @@ public interface Authenticator
* the authentication check.
*/
public void authenticateUser (
- User user, String username, String password, boolean persist)
+ User user, String username, Password password, boolean persist)
throws AuthenticationFailedException;
}
diff --git a/projects/samskivert/src/java/com/samskivert/servlet/user/Password.java b/projects/samskivert/src/java/com/samskivert/servlet/user/Password.java
index c8f1ff13..1fbaf996 100644
--- a/projects/samskivert/src/java/com/samskivert/servlet/user/Password.java
+++ b/projects/samskivert/src/java/com/samskivert/servlet/user/Password.java
@@ -10,22 +10,12 @@ package com.samskivert.servlet.user;
public class Password
{
/**
- * Creates a password from the supplied username and (unencrypted)
- * password.
+ * Returns the clear password text. This method may return null if
+ * none was provided when creating the password.
*/
- public Password (String username, String password)
+ public String getCleartext ()
{
- _encrypted = UserUtil.encryptPassword(username, password);
- }
-
- /**
- * Creates a password directly from the encrypted text. This text
- * must have been created using {@link
- * UserUtil#encryptPassword} or via the same algorithm.
- */
- public Password (String encrypted)
- {
- _encrypted = encrypted;
+ return _cleartext;
}
/**
@@ -36,5 +26,31 @@ public class Password
return _encrypted;
}
+ /**
+ * Creates a password instance from the supplied plaintext.
+ */
+ public static Password makeFromClear (String password)
+ {
+ return new Password(password, UserUtil.encryptPassword(password));
+ }
+
+ /**
+ * Creates a password instance from the supplied already encrypted
+ * text. Note: the encrypted text must be obtained from
+ * {@link UserUtil#encryptPassword}.
+ */
+ public static Password makeFromCrypto (String encrypted)
+ {
+ return new Password(null, encrypted);
+ }
+
+ /** Creates a password instance. */
+ protected Password (String cleartext, String encrypted)
+ {
+ _cleartext = cleartext;
+ _encrypted = encrypted;
+ }
+
+ protected String _cleartext;
protected String _encrypted;
}
diff --git a/projects/samskivert/src/java/com/samskivert/servlet/user/User.java b/projects/samskivert/src/java/com/samskivert/servlet/user/User.java
index 284aaf8e..1f58764a 100644
--- a/projects/samskivert/src/java/com/samskivert/servlet/user/User.java
+++ b/projects/samskivert/src/java/com/samskivert/servlet/user/User.java
@@ -76,7 +76,17 @@ public class User
*/
public void setPassword (String password)
{
- this.password = UserUtil.encryptPassword(username, password);
+ setPassword(Password.makeFromClear(password));
+ }
+
+ /**
+ * Updates the user's password.
+ *
+ * @param password The user's new password.
+ */
+ public void setPassword (Password password)
+ {
+ this.password = password.getEncrypted();
_dirty.setModified("password");
}
@@ -99,20 +109,38 @@ public class User
}
/**
- * Compares the supplied (unencrypted) password with the password
- * associated with this user record.
+ * Converts a legacy password.
+ *
+ * @return true if a conversion took place, false if not.
+ */
+ public boolean updateLegacyPassword (String password)
+ {
+ // we may have an old crypt() encrypted password
+ if (this.password.length() == 13) {
+ // check both the case sensitive and insensitive versions for
+ // further legacy reasons
+ if (this.password.equals(
+ UserUtil.legacyEncrypt(username, password, false)) ||
+ this.password.equals(
+ UserUtil.legacyEncrypt(username, password, true))) {
+ // update our password with the new encryption method
+ setPassword(password);
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Compares the supplied password with the password associated with
+ * this user record.
*
* @return true if the passwords match, false if they do not.
*/
- public boolean passwordsMatch (String password)
+ public boolean passwordsMatch (Password password)
{
- String epasswd = UserUtil.encryptPassword(username, password);
- String oldpasswd = UserUtil.encryptPassword(username, password, false);
- // because we used to be case sensitive, we have to check both
- // versions of the encrypted password here for backward
- // compatibility
- return (this.password.equals(epasswd) ||
- this.password.equals(oldpasswd));
+ return this.password.equals(password.getEncrypted());
}
/**
diff --git a/projects/samskivert/src/java/com/samskivert/servlet/user/UserManager.java b/projects/samskivert/src/java/com/samskivert/servlet/user/UserManager.java
index 439f723f..e0375f75 100644
--- a/projects/samskivert/src/java/com/samskivert/servlet/user/UserManager.java
+++ b/projects/samskivert/src/java/com/samskivert/servlet/user/UserManager.java
@@ -60,7 +60,7 @@ public class UserManager
{
// documentation inherited
public void authenticateUser (
- User user, String username, String password, boolean persist)
+ User user, String username, Password password, boolean persist)
throws InvalidPasswordException
{
// don't care
@@ -75,7 +75,7 @@ public class UserManager
{
// documentation inherited
public void authenticateUser (
- User user, String username, String password, boolean persist)
+ User user, String username, Password password, boolean persist)
throws AuthenticationFailedException
{
if (!user.passwordsMatch(password)) {
@@ -224,7 +224,7 @@ public class UserManager
* or some other error occurs, an exception will be thrown.
*
* @param username The username supplied by the user.
- * @param password The plaintext password supplied by the user.
+ * @param password The password supplied by the user.
* @param persist If true, the cookie will expire in one month, if
* false, the cookie will expire at the end of the user's browser
* session.
@@ -235,7 +235,7 @@ public class UserManager
*
* @return the user object of the authenticated user.
*/
- public User login (String username, String password, boolean persist,
+ public User login (String username, Password password, boolean persist,
HttpServletRequest req, HttpServletResponse rsp,
Authenticator auth)
throws PersistenceException, AuthenticationFailedException
@@ -246,6 +246,13 @@ public class UserManager
throw new NoSuchUserException("error.no_such_user");
}
+ // potentially convert the user's legacy password
+ if (password.getCleartext() != null &&
+ user.updateLegacyPassword(password.getCleartext())) {
+ Log.info("Updated legacy password " + user.username + ".");
+ _repository.updateUser(user);
+ }
+
// run the user through the authentication gamut
auth.authenticateUser(user, username, password, persist);
diff --git a/projects/samskivert/src/java/com/samskivert/servlet/user/UserRepository.java b/projects/samskivert/src/java/com/samskivert/servlet/user/UserRepository.java
index e6447b2e..1d3543e6 100644
--- a/projects/samskivert/src/java/com/samskivert/servlet/user/UserRepository.java
+++ b/projects/samskivert/src/java/com/samskivert/servlet/user/UserRepository.java
@@ -91,29 +91,6 @@ public class UserRepository extends JORARepository
getUserClass().getName(), "users", session, "userId");
}
- /**
- * Requests that a new user be created in the repository.
- *
- * @param uname the username of the new user to create.
- * @param pass the (unencrypted) password for the new user.
- * @param realname the user's real name.
- * @param email the user's email address.
- * @param siteId the unique identifier of the site through which this
- * account is being created. The resulting user will be tracked as
- * originating from this site for accounting purposes ({@link
- * SiteIdentifier#DEFAULT_SITE_ID} can be used by systems that don't
- * desire to perform site tracking.
- *
- * @return The userid of the newly created user.
- */
- public int createUser (Username uname, String pass, String realname,
- String email, int siteId)
- throws UserExistsException, PersistenceException
- {
- return createUser(uname, new Password(uname.getUsername(), pass),
- realname, email, siteId);
- }
-
/**
* Like {@link #createUser(String,String,String,String,int)} except
* that the supplied password has already been encrypted.
@@ -139,11 +116,11 @@ public class UserRepository extends JORARepository
String realname, String email, int siteId)
{
user.username = name.getUsername();
- user.password = pass.getEncrypted();
- user.realname = realname;
- user.email = email;
+ user.setPassword(pass);
+ user.setRealName(realname);
+ user.setEmail(email);
user.created = new Date(System.currentTimeMillis());
- user.siteId = siteId;
+ user.setSiteId(siteId);
}
/**
@@ -606,10 +583,12 @@ public class UserRepository extends JORARepository
System.out.println(rep.loadUser("mdb"));
System.out.println(rep.loadUserBySession("auth"));
- rep.createUser(new Username("samskivert"), "foobar",
+ rep.createUser(new Username("samskivert"),
+ Password.makeFromClear("foobar"),
"Michael Bayne", "mdb@samskivert.com",
SiteIdentifier.DEFAULT_SITE_ID);
- rep.createUser(new Username("mdb"), "foobar", "Michael Bayne",
+ rep.createUser(new Username("mdb"),
+ Password.makeFromClear("foobar"), "Michael Bayne",
"mdb@samskivert.com",
SiteIdentifier.DEFAULT_SITE_ID);
diff --git a/projects/samskivert/src/java/com/samskivert/servlet/user/UserUtil.java b/projects/samskivert/src/java/com/samskivert/servlet/user/UserUtil.java
index 416d5438..288d79bb 100644
--- a/projects/samskivert/src/java/com/samskivert/servlet/user/UserUtil.java
+++ b/projects/samskivert/src/java/com/samskivert/servlet/user/UserUtil.java
@@ -48,26 +48,17 @@ public class UserUtil
* that would be stored in the user record were the password to be
* updated via {@link User#setPassword}.
*/
- public static String encryptPassword (String username, String password)
+ public static String encryptPassword (String password)
{
- return encryptPassword(username, password, true);
+ return StringUtil.md5hex(password);
}
/**
- * Encrypts the user's password according to our preferred scheme.
- *
- * @param username the username of the user whose password is to be
- * encrypted.
- * @param password the plaintext of the password to be encrypted.
- * @param ignoreUserCase true if the username should be uncapitalized
- * prior to performing the encryption so that future password checks
- * will work if the user registers as "Bluebeard" but logs in as
- * "bluebeard".
+ * Encrypts passwords the way we used to.
*/
- public static String encryptPassword (
- String username, String password, boolean ignoreUserCase)
+ public static String legacyEncrypt (String username, String password,
+ boolean ignoreUserCase)
{
- // perhaps we'll not be too (case) sensitive
if (ignoreUserCase) {
username = username.toLowerCase();
}
@@ -77,10 +68,9 @@ public class UserUtil
public static void main (String[] args)
{
if (args.length < 2) {
- System.err.println("Usage: UserUtil username password");
+ System.err.println("Usage: UserUtil password");
System.exit(-1);
}
- System.out.println("Encrypted password: " +
- encryptPassword(args[0], args[1], true));
+ System.out.println("Encrypted password: " + encryptPassword(args[0]));
}
}