package io.milton.mini;
import java.util.Date;
import io.milton.vfs.db.Credential;
import io.milton.vfs.db.PasswordCredential;
import io.milton.vfs.db.Profile;
import io.milton.http.http11.auth.DigestGenerator;
import io.milton.http.http11.auth.DigestResponse;
import io.milton.vfs.db.utils.SessionManager;
import java.util.ArrayList;
/**
*
* @author brad
*/
public class PasswordManager {
private static org.apache.log4j.Logger log = org.apache.log4j.Logger.getLogger(PasswordManager.class);
private final DigestGenerator digestGenerator;
private String realm = "milton-mini";
public PasswordManager(DigestGenerator digestGenerator) {
this.digestGenerator = digestGenerator;
}
public PasswordManager() {
this.digestGenerator = new DigestGenerator();
}
public void setPassword(Profile user, String newPassword) {
// Attempt to locate a PasswordCredential
PasswordCredential epc = null;
if (user.getCredentials() != null) {
for (Credential c : user.getCredentials()) {
if (c instanceof PasswordCredential) {
epc = (PasswordCredential) c;
break;
}
}
}
if (epc == null) {
epc = new PasswordCredential();
epc.setCreatedDate(new Date());
epc.setModifiedDate(new Date());
epc.setProfile(user);
if( user.getCredentials() == null ) {
user.setCredentials(new ArrayList<Credential>());
}
user.getCredentials().add(epc);
}
String hash = calcPasswordHash(user.getName(), newPassword);
epc.setPassword(hash);
SessionManager.session().save(user);
SessionManager.session().save(epc);
}
public String calcPasswordHash(String userName, String password) {
String a1md5 = digestGenerator.encodePasswordInA1Format(userName, realm, password);
return a1md5;
}
public String getRealm() {
return realm;
}
public void setRealm(String realm) {
this.realm = realm;
}
public boolean verifyDigest(DigestResponse digest, Profile user) {
PasswordCredential epc = null;
if (user.getCredentials() != null) {
for (Credential c : user.getCredentials()) {
if (c instanceof PasswordCredential) {
epc = (PasswordCredential) c;
break;
}
}
}
if (epc == null) {
log.warn("Profile is not associated with a password: profileId=" + user.getId());
return false;
}
//String actualPassword = epc.getPassword();
String a1Md5 = epc.getPassword();
//String a1Md5 = digestGenerator.encodePasswordInA1Format(user.getName(), realm, actualPassword);
String expectedResp = digestGenerator.generateDigestWithEncryptedPassword(digest, a1Md5);
String actualResp = digest.getResponseDigest();
if (expectedResp.equals(actualResp)) {
// log.info("verifyDigest: ok");
return true;
} else {
System.out.println("digests don't match!!!!");
System.out.println("expected (ie generated by server): " + expectedResp);
System.out.println("actual (ie given in request): " + actualResp);
System.out.println("cnonce: " + digest.getCnonce());
System.out.println("method: " + digest.getMethod());
System.out.println("nc: " + digest.getNc());
System.out.println("nonce:" + digest.getNonce());
System.out.println("qop: " + digest.getQop());
System.out.println("realm: " + digest.getRealm());
System.out.println("uri: " + digest.getUri());
System.out.println("user: " + digest.getUser());
System.out.println("password a1md5: " + a1Md5);
return false;
}
}
public boolean verifyPassword(Profile user, String requestPassword) {
if (requestPassword != null) {
log.trace("verify password: " + user.getName());
if (user.getCredentials() != null && !user.getCredentials().isEmpty()) {
for (Credential c : user.getCredentials()) {
if (c instanceof PasswordCredential) {
PasswordCredential pc = (PasswordCredential) c;
if (matches(user.getName(), pc, requestPassword)) {
log.trace("Password check ok");
return true;
} else {
log.warn("Non-matching password");
}
}
}
} else {
log.warn("null or empty creds for: " + user.getId());
}
}
log.warn("Basic login failed for user: " + user.getEmail());
return false;
}
private boolean matches(String username, PasswordCredential pc, String requestPassword) {
String a1Md5 = pc.getPassword();
String reqHash = calcPasswordHash(username, requestPassword);
if(a1Md5.equals(reqHash)) {
return true;
} else {
log.warn("password hashes do not match: " + a1Md5 + " != " + reqHash);
return false;
}
}
}