diff --git a/src/main/java/de/jalin/ldapadmin/beans/User.java b/src/main/java/de/jalin/ldapadmin/beans/User.java index 062014c..73d7fb7 100644 --- a/src/main/java/de/jalin/ldapadmin/beans/User.java +++ b/src/main/java/de/jalin/ldapadmin/beans/User.java @@ -1,6 +1,7 @@ package de.jalin.ldapadmin.beans; import java.io.Serializable; +import java.security.NoSuchAlgorithmException; import java.util.ArrayList; import java.util.List; @@ -48,9 +49,10 @@ public class User implements Serializable, LDAPBean { this.password = password; } - public void setAndValidatePassword(String password) throws SimplePasswordException { + public void setAndValidatePassword(String password) throws SimplePasswordException, NoSuchAlgorithmException { final PasswordValidator validator = new PasswordValidator(); validator.validate(password); + validator.createSaltedSHA512Hash(password); this.password = password; } diff --git a/src/main/java/de/jalin/ldapadmin/ldap/PasswordValidator.java b/src/main/java/de/jalin/ldapadmin/ldap/PasswordValidator.java index 99a8224..702a503 100644 --- a/src/main/java/de/jalin/ldapadmin/ldap/PasswordValidator.java +++ b/src/main/java/de/jalin/ldapadmin/ldap/PasswordValidator.java @@ -1,8 +1,20 @@ package de.jalin.ldapadmin.ldap; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; + +import org.apache.commons.codec.binary.Base64; + + public class PasswordValidator { private static final int MIN_PASSWORD_LEN = 6; + private static final Base64 BASE64 = new Base64(); + private static final String LABEL = "{SSHA512}"; + private static final String SALT_CHARACTERS = + "abcdefghijklmnopqrstuvwxyz" + + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + + "0123456789$_"; public void validate(final String password) throws SimplePasswordException { if (password == null || password.isEmpty()) { @@ -38,4 +50,35 @@ public class PasswordValidator { } } + public static String randomSalt() { + final StringBuffer buffer = new StringBuffer(); + for (int i=0; i < 8; i++) { + double randomValue = Math.random() * 64.0f - 0.5d; + int randomIndex = Math.round((float)randomValue); + if (randomIndex < 0 || randomIndex >= SALT_CHARACTERS.length()) { + randomIndex = 0; + } + buffer.append(SALT_CHARACTERS.charAt(randomIndex)); + } + return buffer.toString(); + } + + public String createSaltedSHA512Hash(String passwd) throws NoSuchAlgorithmException { + return createSaltedSHA512Hash(randomSalt(), passwd); + } + + public static String createSaltedSHA512Hash(String salt, String passwd) throws NoSuchAlgorithmException { + final byte[] saltBytes = salt.getBytes(); + MessageDigest sha = MessageDigest.getInstance("SHA-512"); + sha.reset(); + sha.update(passwd.getBytes()); + sha.update(saltBytes); + byte[] pwHash = sha.digest(); + final byte[] hashBytes = new byte[pwHash.length + saltBytes.length]; + System.arraycopy(pwHash, 0, hashBytes, 0, pwHash.length); + System.arraycopy(saltBytes, 0, hashBytes, pwHash.length, saltBytes.length); + final String encode = BASE64.encodeAsString(hashBytes); + return LABEL + new String(encode); + } + } diff --git a/src/main/java/de/jalin/ldapadmin/web/ProfileServlet.java b/src/main/java/de/jalin/ldapadmin/web/ProfileServlet.java index ce45228..4217441 100644 --- a/src/main/java/de/jalin/ldapadmin/web/ProfileServlet.java +++ b/src/main/java/de/jalin/ldapadmin/web/ProfileServlet.java @@ -1,6 +1,7 @@ package de.jalin.ldapadmin.web; import java.io.IOException; +import java.security.NoSuchAlgorithmException; import java.util.List; import java.util.SortedMap; @@ -110,7 +111,8 @@ public class ProfileServlet extends AbstractLDAPServlet { httpSession.setAttribute("errormessage", messages.getString("ProfileServlet.inputfield") + e.getFieldname() + " " + e.getCondition()); req.getRequestDispatcher("/user.jsp").forward(req, resp); return; - } + } catch (NoSuchAlgorithmException e) { + throwServletException(httpSession, e); } try { if ("password".equals(operation)) { final User oldValue = usersDAO.read(dn); diff --git a/src/main/java/de/jalin/ldapadmin/web/ResetPasswordServlet.java b/src/main/java/de/jalin/ldapadmin/web/ResetPasswordServlet.java index 80c5038..4e1297f 100644 --- a/src/main/java/de/jalin/ldapadmin/web/ResetPasswordServlet.java +++ b/src/main/java/de/jalin/ldapadmin/web/ResetPasswordServlet.java @@ -8,6 +8,7 @@ import java.io.PrintStream; import java.io.PrintWriter; import java.io.Writer; import java.net.InetAddress; +import java.security.NoSuchAlgorithmException; import java.util.Collection; import java.util.SortedMap; @@ -17,6 +18,7 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; +import org.apache.commons.lang.CharEncoding; import org.apache.commons.net.smtp.SMTPClient; import org.apache.commons.net.smtp.SMTPReply; import org.apache.commons.net.smtp.SimpleSMTPHeader; @@ -28,7 +30,6 @@ import de.jalin.ldapadmin.hsadmin.MailboxNotFound; import de.jalin.ldapadmin.ldap.LDAPSessionException; import de.jalin.ldapadmin.ldap.SimplePasswordException; import de.jalin.ldapadmin.ldap.UsersDAO; -import org.apache.commons.lang.CharEncoding; @WebServlet(name = "ResetPassword", urlPatterns = {"/passwordreset"}, loadOnStartup = 1) public class ResetPasswordServlet extends AbstractLDAPServlet { @@ -122,7 +123,8 @@ public class ResetPasswordServlet extends AbstractLDAPServlet { return; } throwServletException(httpSession, e); - } + } catch (NoSuchAlgorithmException e) { + throwServletException(httpSession, e); } } } } diff --git a/src/main/java/de/jalin/ldapadmin/web/UserServlet.java b/src/main/java/de/jalin/ldapadmin/web/UserServlet.java index 26d916c..04d82fb 100644 --- a/src/main/java/de/jalin/ldapadmin/web/UserServlet.java +++ b/src/main/java/de/jalin/ldapadmin/web/UserServlet.java @@ -1,6 +1,7 @@ package de.jalin.ldapadmin.web; import java.io.IOException; +import java.security.NoSuchAlgorithmException; import java.util.ArrayList; import java.util.Iterator; import java.util.List; @@ -137,7 +138,9 @@ public class UserServlet extends AbstractLDAPServlet { httpSession.setAttribute("errormessage", messages.getString("UserServlet.input_field") + " \"" + e.getFieldname() + "\" " + e.getCondition()); req.getRequestDispatcher("/user.jsp").forward(req, resp); return; - } + } catch (NoSuchAlgorithmException e) { + throwServletException(httpSession, e); + } } final GroupsDAO groupsDAO = new GroupsDAO(ldapSession); try {