Password hashes are now class instances, not naked strings.

This commit is contained in:
Mark H. Wood
2012-07-11 14:24:04 -04:00
parent f3f9433bfe
commit 9b58faa601
4 changed files with 99 additions and 17 deletions

View File

@@ -32,6 +32,7 @@ import org.dspace.core.Constants;
import org.dspace.core.Context;
import org.dspace.eperson.EPerson;
import org.dspace.eperson.Group;
import org.dspace.eperson.PasswordHash;
import org.jdom.Namespace;
@@ -70,6 +71,8 @@ public class RoleDisseminator implements PackageDisseminator
public static final String LAST_NAME = "LastName";
public static final String LANGUAGE = "Language";
public static final String PASSWORD_HASH = "PasswordHash";
public static final String PASSWORD_DIGEST = "digest";
public static final String PASSWORD_SALT = "salt";
public static final String CAN_LOGIN = "CanLogin";
public static final String REQUIRE_CERTIFICATE = "RequireCertificate";
public static final String SELF_REGISTERED = "SelfRegistered";
@@ -475,8 +478,19 @@ public class RoleDisseminator implements PackageDisseminator
if (emitPassword)
{
PasswordHash password = eperson.getPasswordHash();
writer.writeStartElement(PASSWORD_HASH);
writer.writeCharacters(eperson.getPasswordHash());
String algorithm = password.getAlgorithm();
if (null != algorithm)
writer.writeAttribute(PASSWORD_DIGEST, algorithm);
String salt = password.getSaltString();
if (null != salt)
writer.writeAttribute(PASSWORD_SALT, salt);
writer.writeCharacters(password.getHashString());
writer.writeEndElement();
}

View File

@@ -16,6 +16,7 @@ import java.util.List;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.apache.commons.codec.DecoderException;
import org.dspace.authorize.AuthorizeException;
import org.dspace.content.Collection;
@@ -26,11 +27,10 @@ import org.dspace.core.Constants;
import org.dspace.core.Context;
import org.dspace.eperson.EPerson;
import org.dspace.eperson.Group;
import org.dspace.eperson.PasswordHash;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.w3c.dom.*;
import org.xml.sax.SAXException;
/**
@@ -171,7 +171,30 @@ public class RoleIngester implements PackageIngester
data = user.getElementsByTagName(RoleDisseminator.PASSWORD_HASH);
if (data.getLength() > 0)
{
eperson.setPasswordHash(data.item(0).getTextContent());
Node element = data.item(0);
NamedNodeMap attributes = element.getAttributes();
Node algorithm = attributes.getNamedItem(RoleDisseminator.PASSWORD_DIGEST);
String algorithmText;
if (null != algorithm)
algorithmText = algorithm.getNodeValue();
else
algorithmText = null;
Node salt = attributes.getNamedItem(RoleDisseminator.PASSWORD_SALT);
String saltText;
if (null != salt)
saltText = salt.getNodeValue();
else
saltText = null;
PasswordHash password;
try {
password = new PasswordHash(algorithmText, saltText, element.getTextContent());
} catch (DecoderException ex) {
throw new PackageValidationException("Unable to decode hexadecimal password hash or salt", ex);
}
eperson.setPasswordHash(password);
}
else
{

View File

@@ -11,7 +11,6 @@ import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.codec.DecoderException;
import org.apache.commons.codec.binary.Hex;
import org.apache.log4j.Logger;
import org.dspace.authorize.AuthorizeException;
@@ -869,26 +868,43 @@ public class EPerson extends DSpaceObject
/**
* Set the EPerson's password hash.
* FIXME include the salt and algorithm
*
* @param s
* hash of the password
* @param password
* hashed password, or null to set row data to NULL.
*/
public void setPasswordHash(String s)
public void setPasswordHash(PasswordHash password)
{
myRow.setColumn("password", s);
if (null == password)
{
myRow.setColumnNull("digest_algorithm");
myRow.setColumnNull("salt");
myRow.setColumnNull("password");
}
else
{
myRow.setColumn("digest_algorithm", password.getAlgorithm());
myRow.setColumn("salt", password.getSaltString());
myRow.setColumn("password", password.getHashString());
}
modified = true;
}
/**
* Return the EPerson's password hash.
* FIXME return an actual PasswordHash
*
* @return hash of the password
*/
public String getPasswordHash()
public PasswordHash getPasswordHash()
{
return myRow.getStringColumn("password");
PasswordHash hash = null;
try {
hash = new PasswordHash(myRow.getStringColumn("digestAlgorithm"),
myRow.getStringColumn("salt"),
myRow.getStringColumn("password"));
} catch (DecoderException ex) {
log.error("Problem decoding stored salt or hash: " + ex.getMessage());
}
return hash;
}
/**

View File

@@ -85,6 +85,9 @@ public class PasswordHash
else
this.algorithm = algorithm;
if (null == salt)
this.salt = null;
else
this.salt = Hex.decodeHex(salt.toCharArray());
this.hash = Hex.decodeHex(hash.toCharArray());
@@ -132,7 +135,7 @@ public class PasswordHash
}
/**
* Get the value of hash
* Get the hash.
*
* @return the value of hash
*/
@@ -142,7 +145,20 @@ public class PasswordHash
}
/**
* Get the value of salt
* Get the hash, as a String.
*
* @return hash encoded as hexadecimal digits, or null if none.
*/
public String getHashString()
{
if (null != hash)
return new String(Hex.encodeHex(hash));
else
return null;
}
/**
* Get the salt.
*
* @return the value of salt
*/
@@ -151,6 +167,19 @@ public class PasswordHash
return salt;
}
/**
* Get the salt, as a String.
*
* @return salt encoded as hexadecimal digits, or null if none.
*/
public String getSaltString()
{
if (null != salt)
return new String(Hex.encodeHex(salt));
else
return null;
}
/**
* Get the value of algorithm
*