package org.cagrid.gaards.dorian.idp; import gov.nih.nci.cagrid.common.FaultHelper; import gov.nih.nci.cagrid.common.Utils; import java.io.IOException; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.util.ArrayList; import java.util.Date; import java.util.List; import org.cagrid.gaards.authentication.BasicAuthentication; import org.cagrid.gaards.authentication.Credential; import org.cagrid.gaards.authentication.faults.CredentialNotSupportedFault; import org.cagrid.gaards.authentication.faults.InvalidCredentialFault; import org.cagrid.gaards.dorian.common.AuditConstants; import org.cagrid.gaards.dorian.common.LoggingObject; import org.cagrid.gaards.dorian.service.util.AddressValidator; import org.cagrid.gaards.dorian.service.util.Crypt; import org.cagrid.gaards.dorian.stubs.types.DorianInternalFault; import org.cagrid.gaards.dorian.stubs.types.InvalidUserPropertyFault; import org.cagrid.gaards.dorian.stubs.types.NoSuchUserFault; import org.cagrid.gaards.dorian.stubs.types.PermissionDeniedFault; import org.cagrid.tools.database.Database; import org.cagrid.tools.events.EventManager; /** * @author <A href="mailto:langella@bmi.osu.edu">Stephen Langella </A> * @author <A href="mailto:oster@bmi.osu.edu">Scott Oster </A> * @author <A href="mailto:hastings@bmi.osu.edu">Shannon Hastings </A> * @version $Id: ArgumentManagerTable.java,v 1.2 2004/10/15 16:35:16 langella * Exp $ */ public class UserManager extends LoggingObject { public final static String PASSWORD_ERROR_MESSAGE = "The uid or password is incorrect."; public final static int SYSTEM_MAX_PASSWORD_LENGTH = 30; public final static String SYSTEM_MAX_PASSWORD_ERROR_PREFIX = "Unacceptable password, the length of the password cannot exceed the maximum system password length of "; public static String INVALID_PASSWORD_MESSAGE = "Invalid password, a valid password CANNOT contain a dictionary word and MUST contain at least one upper case letter, at least one lower case letter, at least one number, and at least one symbol (~!@#$%^&*()_-+={}[]|:;<>,.?)"; public static String ADMIN_USER_ID = "dorian"; public static String ADMIN_PASSWORD = "DorianAdmin$1"; public static final String IDP_USERS_TABLE = "idp_users"; private Database db; private boolean dbBuilt = false; private IdentityProviderProperties conf; private PasswordSecurityManager passwordSecurityManager; public UserManager(Database db, IdentityProviderProperties conf) throws DorianInternalFault { this.db = db; this.conf = conf; this.passwordSecurityManager = new PasswordSecurityManager(db, conf.getPasswordSecurityPolicy()); } public LocalUser authenticateAndVerifyUser(Credential credential, EventManager eventManager) throws DorianInternalFault, InvalidCredentialFault, CredentialNotSupportedFault { if (credential.getClass().equals(BasicAuthentication.class)) { BasicAuthentication cred = (BasicAuthentication) credential; try { LocalUser u = getUser(cred.getUserId()); PasswordSecurity entry = this.passwordSecurityManager.getEntry(u.getUserId(), true); PasswordStatus status = entry.getPasswordStatus(); String suppliedPassword = cred.getPassword(); if (suppliedPassword.length() > SYSTEM_MAX_PASSWORD_LENGTH) { InvalidCredentialFault fault = new InvalidCredentialFault(); fault.setFaultString(PASSWORD_ERROR_MESSAGE); throw fault; } if (status.equals(PasswordStatus.Valid)) { String digest = null; boolean crypt = false; if ((entry.getDigestAlgorithm() == null) || (entry.getDigestAlgorithm().equals(PasswordSecurityManager.CRYPT_DIGEST_ALGORITHM))) { crypt = true; digest = Crypt.crypt(suppliedPassword); } else if (entry.getDigestAlgorithm().equals(PasswordSecurityManager.PASSWORD_DIGEST_ALGORITHM)) { try { digest = PasswordSecurityManager.encrypt(suppliedPassword, entry.getDigestSalt()); } catch (Exception e) { log.error(e); DorianInternalFault fault = new DorianInternalFault(); fault.setFaultString("Unexpected error calculating password digest!!!"); throw fault; } } else { DorianInternalFault fault = new DorianInternalFault(); fault.setFaultString("Could not obtain password digest, unknown digest algorithm (" + entry.getDigestAlgorithm() + ")!!!"); throw fault; } if (!u.getPassword().equals(digest)) { this.passwordSecurityManager.reportInvalidLoginAttempt(u.getUserId()); PasswordSecurity ps = this.passwordSecurityManager.getEntry(u.getUserId()); if (ps.getPasswordStatus().equals(PasswordStatus.Locked)) { Date unlock = new Date(ps.getLockoutExpiration()); if (eventManager != null) { eventManager.logEvent(u.getUserId(), AuditConstants.SYSTEM_ID, IdentityProviderAudit.LocalAccountLocked.getValue(), "Account locked because of to many consecutive invalid logins (" + conf.getPasswordSecurityPolicy().getConsecutiveInvalidLogins() + "). The lock will expire on " + unlock.toString() + "."); } } else if (ps.getPasswordStatus().equals(PasswordStatus.LockedUntilChanged)) { if (eventManager != null) { eventManager .logEvent( u.getUserId(), AuditConstants.SYSTEM_ID, IdentityProviderAudit.LocalAccountLocked.getValue(), "Account locked because of to many total invalid logins (" + conf.getPasswordSecurityPolicy().getTotalInvalidLogins() + "). The lock will not expire until the account password is reset by an administrator."); } } InvalidCredentialFault fault = new InvalidCredentialFault(); fault.setFaultString(PASSWORD_ERROR_MESSAGE); throw fault; } else { this.passwordSecurityManager.reportSuccessfulLoginAttempt(u.getUserId()); if (crypt) { u.setPassword(suppliedPassword); try { updateUser(u); if (eventManager != null) { eventManager.logEvent(u.getUserId(), AuditConstants.SYSTEM_ID, IdentityProviderAudit.LocalAccountUpdated.getValue(), "Password encryption algorithm updated from crypt to " + PasswordSecurityManager.PASSWORD_DIGEST_ALGORITHM + "."); } } catch (Exception e) { log.error(e); DorianInternalFault fault = new DorianInternalFault(); fault.setFaultString("Unexpected error upgrading password digest."); throw fault; } } } } else if (status.equals(PasswordStatus.LockedUntilChanged)) { InvalidCredentialFault fault = new InvalidCredentialFault(); fault .setFaultString("This account has been locked because the maximum number of invalid logins has been exceeded, please contact an administrator to have your password reset."); throw fault; } else if (status.equals(PasswordStatus.Locked)) { InvalidCredentialFault fault = new InvalidCredentialFault(); fault .setFaultString("This account has been temporarily locked because the maximum number of consecutive invalid logins has been exceeded."); throw fault; } else { InvalidCredentialFault fault = new InvalidCredentialFault(); fault.setFaultString("Unexpected security status code received."); throw fault; } try { verifyUser(u); } catch (PermissionDeniedFault e) { InvalidCredentialFault fault = new InvalidCredentialFault(); fault.setFaultString(e.getFaultString()); throw fault; } return u; } catch (NoSuchUserFault e) { InvalidCredentialFault fault = new InvalidCredentialFault(); fault.setFaultString("User Id or password is incorrect"); throw fault; } catch (DorianInternalFault e) { logError(e.getMessage(), e); DorianInternalFault fault = new DorianInternalFault(); fault.setFaultString("An unexpected database error occurred."); FaultHelper helper = new FaultHelper(fault); helper.addFaultCause(e); fault = (DorianInternalFault) helper.getFault(); throw fault; } } else { CredentialNotSupportedFault fault = new CredentialNotSupportedFault(); fault.setFaultString("The credential provided is not supported."); throw fault; } } public void verifyUser(LocalUser u) throws DorianInternalFault, PermissionDeniedFault { if (!u.getStatus().equals(LocalUserStatus.Active)) { if (u.getStatus().equals(LocalUserStatus.Suspended)) { PermissionDeniedFault fault = new PermissionDeniedFault(); fault.setFaultString("The account has been suspended."); throw fault; } else if (u.getStatus().equals(LocalUserStatus.Rejected)) { PermissionDeniedFault fault = new PermissionDeniedFault(); fault.setFaultString("The application for the account was rejected."); throw fault; } else if (u.getStatus().equals(LocalUserStatus.Pending)) { PermissionDeniedFault fault = new PermissionDeniedFault(); fault.setFaultString("The application for this account has not yet been reviewed."); throw fault; } else { PermissionDeniedFault fault = new PermissionDeniedFault(); fault.setFaultString("Unknown Reason"); throw fault; } } } private void validateSpecifiedField(String fieldName, String name) throws InvalidUserPropertyFault { try { AddressValidator.validateField(fieldName, name); } catch (Exception e) { InvalidUserPropertyFault fault = new InvalidUserPropertyFault(); fault.setFaultString(e.getMessage()); throw fault; } } private void validateEmail(String email) throws InvalidUserPropertyFault { try { AddressValidator.validateEmail(email); } catch (Exception e) { InvalidUserPropertyFault fault = new InvalidUserPropertyFault(); fault.setFaultString(e.getMessage()); throw fault; } } private void validatePassword(LocalUser user) throws DorianInternalFault, InvalidUserPropertyFault { String password = user.getPassword(); if (password == null) { InvalidUserPropertyFault fault = new InvalidUserPropertyFault(); fault.setFaultString("Unacceptable password, the length of the password must be between " + conf.getPasswordSecurityPolicy().getMinPasswordLength() + " and " + conf.getPasswordSecurityPolicy().getMaxPasswordLength() + " characters."); throw fault; } else if (password.length() > SYSTEM_MAX_PASSWORD_LENGTH) { InvalidUserPropertyFault fault = new InvalidUserPropertyFault(); fault.setFaultString(SYSTEM_MAX_PASSWORD_ERROR_PREFIX + +SYSTEM_MAX_PASSWORD_LENGTH + "."); throw fault; } else if ((conf.getPasswordSecurityPolicy().getMinPasswordLength() > password.length()) || (conf.getPasswordSecurityPolicy().getMaxPasswordLength() < password.length())) { InvalidUserPropertyFault fault = new InvalidUserPropertyFault(); fault.setFaultString("Unacceptable password, the length of the password must be between " + conf.getPasswordSecurityPolicy().getMinPasswordLength() + " and " + conf.getPasswordSecurityPolicy().getMaxPasswordLength() + " characters."); throw fault; } else { boolean hasDictionaryWord = true; try { hasDictionaryWord = DictionaryCheck.doesStringContainDictionaryWord(password); } catch (IOException e) { logError(e.getMessage(), e); DorianInternalFault fault = new DorianInternalFault(); fault .setFaultString("Unexpected error validating the user's password, please contact an administrator."); throw fault; } boolean hasCapital = PasswordUtils.hasCapitalLetter(password); boolean hasLowerCase = PasswordUtils.hasLowerCaseLetter(password); boolean hasNumber = PasswordUtils.hasNumber(password); boolean hasSymbol = PasswordUtils.hasSymbol(password); if ((!hasCapital) || (!hasLowerCase) || (!hasNumber) || (!hasSymbol) || (hasDictionaryWord)) { InvalidUserPropertyFault fault = new InvalidUserPropertyFault(); fault.setFaultString(INVALID_PASSWORD_MESSAGE); throw fault; } } } private void validateUserId(LocalUser user) throws InvalidUserPropertyFault { String uid = user.getUserId(); if ((uid == null) || (conf.getMinUserIdLength() > uid.length()) || (conf.getMaxUserIdLength() < uid.length())) { InvalidUserPropertyFault fault = new InvalidUserPropertyFault(); fault.setFaultString("Unacceptable User ID, the length of the user id must be between " + conf.getMinUserIdLength() + " and " + conf.getMaxUserIdLength() + " characters."); throw fault; } } private void validateUser(LocalUser user) throws DorianInternalFault, InvalidUserPropertyFault { validateUserId(user); validatePassword(user); validateSpecifiedField("First Name", user.getFirstName()); validateSpecifiedField("Last Name", user.getLastName()); validateSpecifiedField("Address", user.getAddress()); validateSpecifiedField("City", user.getCity()); validateSpecifiedField("Organization", user.getOrganization()); validateSpecifiedField("Zip Code", user.getZipcode()); validateSpecifiedField("Phone", user.getPhoneNumber()); validateEmail(user.getEmail()); } public synchronized void addUser(LocalUser user) throws DorianInternalFault, InvalidUserPropertyFault { this.buildDatabase(); this.validateUser(user); if (userExists(user.getUserId())) { InvalidUserPropertyFault fault = new InvalidUserPropertyFault(); fault.setFaultString("The user " + user.getUserId() + " already exists."); throw fault; } Connection c = null; try { String passwordSalt = PasswordSecurityManager.getRandomSalt(); String passwordDigest = PasswordSecurityManager.encrypt(user.getPassword(), passwordSalt); c = db.getConnection(); PreparedStatement ps = c .prepareStatement("INSERT INTO " + IDP_USERS_TABLE + " SET UID = ?, EMAIL= ?, PASSWORD= ?, FIRST_NAME= ?, LAST_NAME= ?, ORGANIZATION= ?, ADDRESS= ?, ADDRESS2= ?,CITY= ?, STATE= ?, ZIP_CODE= ?, COUNTRY= ?, PHONE_NUMBER= ?, STATUS= ?, ROLE= ?"); ps.setString(1, user.getUserId()); ps.setString(2, user.getEmail()); ps.setString(3, passwordDigest); ps.setString(4, user.getFirstName()); ps.setString(5, user.getLastName()); ps.setString(6, user.getOrganization()); ps.setString(7, user.getAddress()); if (Utils.clean(user.getAddress2()) == null) { ps.setString(8, ""); } else { ps.setString(8, user.getAddress2()); } ps.setString(9, user.getCity()); ps.setString(10, user.getState().getValue()); ps.setString(11, user.getZipcode()); ps.setString(12, user.getCountry().getValue()); ps.setString(13, user.getPhoneNumber()); ps.setString(14, user.getStatus().getValue()); ps.setString(15, user.getRole().getValue()); ps.executeUpdate(); ps.close(); this.passwordSecurityManager.resetEntry(user.getUserId(), passwordSalt); user.setPasswordSecurity(this.passwordSecurityManager.getEntry(user.getUserId(), true)); } catch (Exception e) { try { this.removeUser(user.getUserId()); } catch (Exception ex) { } try { this.passwordSecurityManager.deleteEntry(user.getUserId()); } catch (Exception ex) { } logError(e.getMessage(), e); DorianInternalFault fault = new DorianInternalFault(); fault.setFaultString("Unexpected Error, Could not add user!!!"); FaultHelper helper = new FaultHelper(fault); helper.addFaultCause(e); fault = (DorianInternalFault) helper.getFault(); throw fault; } finally { db.releaseConnection(c); } } public synchronized void removeUser(String uid) throws DorianInternalFault { this.buildDatabase(); Connection c = null; try { c = db.getConnection(); PreparedStatement ps = c.prepareStatement("DELETE FROM " + IDP_USERS_TABLE + " WHERE UID= ?"); ps.setString(1, uid); ps.executeUpdate(); ps.close(); this.passwordSecurityManager.deleteEntry(uid); } catch (Exception e) { logError(e.getMessage(), e); DorianInternalFault fault = new DorianInternalFault(); fault.setFaultString("Unexpected Error, Could not delete user!!!"); FaultHelper helper = new FaultHelper(fault); helper.addFaultCause(e); fault = (DorianInternalFault) helper.getFault(); throw fault; } finally { db.releaseConnection(c); } } public LocalUser[] getUsers(LocalUserFilter filter) throws DorianInternalFault { return getUsers(filter, true); } public LocalUser[] getUsers(LocalUserFilter filter, boolean includePassword) throws DorianInternalFault { this.buildDatabase(); Connection c = null; List<LocalUser> users = new ArrayList<LocalUser>(); try { c = db.getConnection(); PreparedStatement ps = null; if (filter != null) { ps = c .prepareStatement("select * from " + IDP_USERS_TABLE + " WHERE UID LIKE ? AND EMAIL LIKE ? AND FIRST_NAME LIKE ? AND LAST_NAME LIKE ? AND ORGANIZATION LIKE ? AND ADDRESS LIKE ? AND ADDRESS2 LIKE ? AND CITY LIKE ? AND STATE LIKE ? AND ZIP_CODE LIKE ? AND COUNTRY LIKE ? AND PHONE_NUMBER LIKE ? AND STATUS LIKE ? AND ROLE LIKE ?"); if (filter.getUserId() != null) { ps.setString(1, "%" + filter.getUserId() + "%"); } else { ps.setString(1, "%"); } if (filter.getEmail() != null) { ps.setString(2, "%" + filter.getEmail() + "%"); } else { ps.setString(2, "%"); } if (filter.getFirstName() != null) { ps.setString(3, "%" + filter.getFirstName() + "%"); } else { ps.setString(3, "%"); } if (filter.getLastName() != null) { ps.setString(4, "%" + filter.getLastName() + "%"); } else { ps.setString(4, "%"); } if (filter.getOrganization() != null) { ps.setString(5, "%" + filter.getOrganization() + "%"); } else { ps.setString(5, "%"); } if (filter.getAddress() != null) { ps.setString(6, "%" + filter.getAddress() + "%"); } else { ps.setString(6, "%"); } if (filter.getAddress2() != null) { ps.setString(7, "%" + filter.getAddress2() + "%"); } else { ps.setString(7, "%"); } if (filter.getCity() != null) { ps.setString(8, "%" + filter.getCity() + "%"); } else { ps.setString(8, "%"); } if (filter.getState() != null) { ps.setString(9, "%" + filter.getState() + "%"); } else { ps.setString(9, "%"); } if (filter.getZipcode() != null) { ps.setString(10, "%" + filter.getZipcode() + "%"); } else { ps.setString(10, "%"); } if (filter.getCountry() != null) { ps.setString(11, "%" + filter.getCountry() + "%"); } else { ps.setString(11, "%"); } if (filter.getPhoneNumber() != null) { ps.setString(12, "%" + filter.getPhoneNumber() + "%"); } else { ps.setString(12, "%"); } if (filter.getStatus() != null) { ps.setString(13, filter.getStatus().getValue()); } else { ps.setString(13, "%"); } if (filter.getRole() != null) { ps.setString(14, filter.getRole().getValue()); } else { ps.setString(14, "%"); } } else { ps = c.prepareStatement("select * from " + IDP_USERS_TABLE); } // System.out.println(ps.toString()); ResultSet rs = ps.executeQuery(); while (rs.next()) { LocalUser user = new LocalUser(); user.setUserId(rs.getString("UID")); user.setEmail(rs.getString("EMAIL")); if (includePassword) { user.setPassword(rs.getString("PASSWORD")); } user.setFirstName(rs.getString("FIRST_NAME")); user.setLastName(rs.getString("LAST_NAME")); user.setOrganization(rs.getString("ORGANIZATION")); user.setAddress(rs.getString("ADDRESS")); user.setAddress2(rs.getString("ADDRESS2")); user.setCity(rs.getString("CITY")); user.setState(StateCode.fromValue(rs.getString("STATE"))); user.setZipcode(rs.getString("ZIP_CODE")); user.setCountry(CountryCode.fromValue(rs.getString("COUNTRY"))); user.setPhoneNumber(rs.getString("PHONE_NUMBER")); user.setStatus(LocalUserStatus.fromValue(rs.getString("STATUS"))); user.setRole(LocalUserRole.fromValue(rs.getString("ROLE"))); if (includePassword) { user.setPasswordSecurity(this.passwordSecurityManager.getEntry(user.getUserId(), true)); } else { user.setPasswordSecurity(this.passwordSecurityManager.getEntry(user.getUserId(), false)); } users.add(user); } rs.close(); ps.close(); LocalUser[] list = new LocalUser[users.size()]; for (int i = 0; i < list.length; i++) { list[i] = (LocalUser) users.get(i); } return list; } catch (Exception e) { logError(e.getMessage(), e); DorianInternalFault fault = new DorianInternalFault(); fault.setFaultString("Unexpected Error, could not obtain a list of users"); FaultHelper helper = new FaultHelper(fault); helper.addFaultCause(e); fault = (DorianInternalFault) helper.getFault(); throw fault; } finally { db.releaseConnection(c); } } public LocalUser getUser(String uid) throws DorianInternalFault, NoSuchUserFault { return this.getUser(uid, true); } public LocalUser getUser(String uid, boolean includePassword) throws DorianInternalFault, NoSuchUserFault { this.buildDatabase(); LocalUser user = new LocalUser(); Connection c = null; try { c = db.getConnection(); PreparedStatement s = c.prepareStatement("select * from " + IDP_USERS_TABLE + " where UID= ?"); s.setString(1, uid); ResultSet rs = s.executeQuery(); if (rs.next()) { user.setUserId(uid); user.setEmail(rs.getString("EMAIL")); if (includePassword) { user.setPassword(rs.getString("PASSWORD")); } user.setFirstName(rs.getString("FIRST_NAME")); user.setLastName(rs.getString("LAST_NAME")); user.setOrganization(rs.getString("ORGANIZATION")); user.setAddress(rs.getString("ADDRESS")); user.setAddress2(rs.getString("ADDRESS2")); user.setCity(rs.getString("CITY")); user.setState(StateCode.fromValue(rs.getString("STATE"))); user.setZipcode(rs.getString("ZIP_CODE")); user.setCountry(CountryCode.fromValue(rs.getString("COUNTRY"))); user.setPhoneNumber(rs.getString("PHONE_NUMBER")); user.setStatus(LocalUserStatus.fromValue(rs.getString("STATUS"))); user.setRole(LocalUserRole.fromValue(rs.getString("ROLE"))); if (includePassword) { user.setPasswordSecurity(this.passwordSecurityManager.getEntry(uid, true)); } else { user.setPasswordSecurity(this.passwordSecurityManager.getEntry(uid, false)); } } else { NoSuchUserFault fault = new NoSuchUserFault(); fault.setFaultString("The user " + uid + " does not exist."); throw fault; } rs.close(); s.close(); } catch (NoSuchUserFault f) { throw f; } catch (Exception e) { logError(e.getMessage(), e); DorianInternalFault fault = new DorianInternalFault(); fault.setFaultString("Unexpected Error, could not obtain the user " + uid + "."); FaultHelper helper = new FaultHelper(fault); helper.addFaultCause(e); fault = (DorianInternalFault) helper.getFault(); throw fault; } finally { db.releaseConnection(c); } return user; } public void buildDatabase() throws DorianInternalFault { if (!dbBuilt) { try { if (!this.db.tableExists(IDP_USERS_TABLE)) { String applications = "CREATE TABLE " + IDP_USERS_TABLE + " (" + "UID VARCHAR(255) NOT NULL PRIMARY KEY," + "EMAIL VARCHAR(255) NOT NULL," + "PASSWORD VARCHAR(255) NOT NULL," + "FIRST_NAME VARCHAR(255) NOT NULL," + "LAST_NAME VARCHAR(255) NOT NULL," + "ORGANIZATION VARCHAR(255) NOT NULL," + "ADDRESS VARCHAR(255) NOT NULL," + "ADDRESS2 VARCHAR(255)," + "CITY VARCHAR(255) NOT NULL," + "STATE VARCHAR(20) NOT NULL," + "ZIP_CODE VARCHAR(20) NOT NULL," + "COUNTRY VARCHAR(2) NOT NULL," + "PHONE_NUMBER VARCHAR(20) NOT NULL," + "STATUS VARCHAR(20) NOT NULL," + "ROLE VARCHAR(20) NOT NULL," + "INDEX document_index (EMAIL));"; db.update(applications); try { LocalUser u = new LocalUser(); u.setUserId(ADMIN_USER_ID); u.setPassword(ADMIN_PASSWORD); u.setEmail("dorian@dorian.org"); u.setFirstName("Mr."); u.setLastName("Administrator"); u.setOrganization("caBIG"); u.setAddress("3184 Graves Hall"); u.setAddress2("333 W. Tenth Avenue"); u.setCity("Columbus"); u.setState(StateCode.OH); u.setZipcode("43210"); u.setCountry(CountryCode.US); u.setPhoneNumber("555-555-5555"); u.setStatus(LocalUserStatus.Active); u.setRole(LocalUserRole.Administrator); this.addUser(u); } catch (Exception e) { logError(e.getMessage(), e); DorianInternalFault fault = new DorianInternalFault(); fault.setFaultString("Unexpected Error, Could not add initial IdP user!!!"); FaultHelper helper = new FaultHelper(fault); helper.addFaultCause(e); fault = (DorianInternalFault) helper.getFault(); throw fault; } } this.dbBuilt = true; } catch (DorianInternalFault e) { throw e; } catch (Exception e) { logError(e.getMessage(), e); DorianInternalFault fault = new DorianInternalFault(); fault.setFaultString("An unexpected database error occurred."); FaultHelper helper = new FaultHelper(fault); helper.addFaultCause(e); fault = (DorianInternalFault) helper.getFault(); throw fault; } } } public synchronized void updateUser(LocalUser u) throws DorianInternalFault, NoSuchUserFault, InvalidUserPropertyFault { this.buildDatabase(); if (u.getUserId() == null) { NoSuchUserFault fault = new NoSuchUserFault(); fault.setFaultString("Could not update user, the user " + u.getUserId() + " does not exist."); throw fault; } else if (userExists(u.getUserId())) { String passwordSalt = null; StringBuffer sb = new StringBuffer(); sb.append("update " + IDP_USERS_TABLE + " SET "); int changes = 0; LocalUser curr = this.getUser(u.getUserId()); boolean passwordChanged = false; if (u.getPassword() != null) { String newPasswordDigest = null; String existingDigestAlgorithm = curr.getPasswordSecurity().getDigestAlgorithm(); if ((existingDigestAlgorithm == null) || (existingDigestAlgorithm.equals(PasswordSecurityManager.CRYPT_DIGEST_ALGORITHM))) { newPasswordDigest = Crypt.crypt(u.getPassword()); } else if (existingDigestAlgorithm.equals(PasswordSecurityManager.PASSWORD_DIGEST_ALGORITHM)) { try { newPasswordDigest = PasswordSecurityManager.encrypt(u.getPassword(), curr.getPasswordSecurity() .getDigestSalt()); } catch (Exception e) { log.error(e); DorianInternalFault fault = new DorianInternalFault(); fault.setFaultString("Unexpected error calculating password digest!!!"); throw fault; } } else { DorianInternalFault fault = new DorianInternalFault(); fault.setFaultString("Could not obtain password digest, unknown digest algorithm (" + existingDigestAlgorithm + ")!!!"); throw fault; } if (!newPasswordDigest.equals(curr.getPassword())) { validatePassword(u); String newPass = null; try { passwordSalt = PasswordSecurityManager.getRandomSalt(); newPass = PasswordSecurityManager.encrypt(u.getPassword(), passwordSalt); } catch (Exception e) { log.error(e); DorianInternalFault fault = new DorianInternalFault(); fault .setFaultString("Could not update user, unexpected error calculating the password digest."); throw fault; } curr.setPassword(newPass); passwordChanged = true; } } if ((u.getEmail() != null) && (!u.getEmail().equals(curr.getEmail()))) { validateEmail(u.getEmail()); curr.setEmail(u.getEmail()); } if ((u.getFirstName() != null) && (!u.getFirstName().equals(curr.getFirstName()))) { validateSpecifiedField("First Name", u.getFirstName()); curr.setFirstName(u.getFirstName()); } if ((u.getLastName() != null) && (!u.getLastName().equals(curr.getLastName()))) { validateSpecifiedField("Last Name", u.getLastName()); curr.setLastName(u.getLastName()); } if ((u.getOrganization() != null) && (!u.getOrganization().equals(curr.getOrganization()))) { validateSpecifiedField("Organization", u.getOrganization()); curr.setOrganization(u.getOrganization()); } if ((u.getAddress() != null) && (!u.getAddress().equals(curr.getAddress()))) { validateSpecifiedField("Address", u.getAddress()); curr.setAddress(u.getAddress()); } if ((u.getAddress2() != null) && (!u.getAddress2().equals(curr.getAddress2()))) { curr.setAddress2(u.getAddress2()); } if ((u.getCity() != null) && (!u.getCity().equals(curr.getCity()))) { validateSpecifiedField("City", u.getCity()); curr.setCity(u.getCity()); } if ((u.getState() != null) && (!u.getState().equals(curr.getState()))) { curr.setState(u.getState()); } if ((u.getCountry() != null) && (!u.getCountry().equals(curr.getCountry()))) { curr.setCountry(u.getCountry()); } if ((u.getZipcode() != null) && (!u.getZipcode().equals(curr.getZipcode()))) { validateSpecifiedField("Zip Code", u.getZipcode()); curr.setZipcode(u.getZipcode()); } if ((u.getPhoneNumber() != null) && (!u.getPhoneNumber().equals(curr.getPhoneNumber()))) { validateSpecifiedField("Phone Number", u.getPhoneNumber()); curr.setPhoneNumber(u.getPhoneNumber()); } if ((u.getStatus() != null) && (!u.getStatus().equals(curr.getStatus()))) { if (accountCreated(curr.getStatus()) && !accountCreated(u.getStatus())) { InvalidUserPropertyFault fault = new InvalidUserPropertyFault(); fault.setFaultString("Error, cannot change " + u.getUserId() + "'s status from a post-created account status (" + curr.getStatus() + ") to a pre-created account status (" + u.getStatus() + ")."); throw fault; } curr.setStatus(u.getStatus()); } if ((u.getRole() != null) && (!u.getRole().equals(curr.getRole()))) { if (changes > 0) { sb.append(","); } curr.setRole(u.getRole()); } Connection c = null; try { c = db.getConnection(); PreparedStatement ps = c .prepareStatement("UPDATE " + IDP_USERS_TABLE + " SET UID = ?, EMAIL= ?, PASSWORD= ?, FIRST_NAME= ?, LAST_NAME= ?, ORGANIZATION= ?, ADDRESS= ?, ADDRESS2= ?,CITY= ?, STATE= ?, ZIP_CODE= ?, COUNTRY= ?, PHONE_NUMBER= ?, STATUS= ?, ROLE= ? WHERE UID = ?"); ps.setString(1, curr.getUserId()); ps.setString(2, curr.getEmail()); ps.setString(3, curr.getPassword()); ps.setString(4, curr.getFirstName()); ps.setString(5, curr.getLastName()); ps.setString(6, curr.getOrganization()); ps.setString(7, curr.getAddress()); ps.setString(8, curr.getAddress2()); ps.setString(9, curr.getCity()); ps.setString(10, curr.getState().getValue()); ps.setString(11, curr.getZipcode()); ps.setString(12, curr.getCountry().getValue()); ps.setString(13, curr.getPhoneNumber()); ps.setString(14, curr.getStatus().getValue()); ps.setString(15, curr.getRole().getValue()); ps.setString(16, curr.getUserId()); ps.executeUpdate(); ps.close(); if (passwordChanged) { this.passwordSecurityManager.resetEntry(curr.getUserId(), passwordSalt); u.setPasswordSecurity(this.passwordSecurityManager.getEntry(curr.getUserId(), false)); } } catch (Exception e) { logError(e.getMessage(), e); DorianInternalFault fault = new DorianInternalFault(); fault.setFaultString("Unexpected Error, Could not update user!!!"); FaultHelper helper = new FaultHelper(fault); helper.addFaultCause(e); fault = (DorianInternalFault) helper.getFault(); throw fault; } finally { db.releaseConnection(c); } } else { NoSuchUserFault fault = new NoSuchUserFault(); fault.setFaultString("Could not update user, the user " + u.getUserId() + " does not exist."); throw fault; } } private boolean accountCreated(LocalUserStatus status) { if (status.equals(LocalUserStatus.Suspended)) { return true; } else if (status.equals(LocalUserStatus.Active)) { return true; } else { return false; } } public boolean userExists(String uid) throws DorianInternalFault { this.buildDatabase(); Connection c = null; boolean exists = false; try { c = db.getConnection(); PreparedStatement s = c.prepareStatement("select count(*) from " + IDP_USERS_TABLE + " where UID= ?"); s.setString(1, uid); ResultSet rs = s.executeQuery(); if (rs.next()) { int count = rs.getInt(1); if (count > 0) { exists = true; } } rs.close(); s.close(); } catch (Exception e) { logError(e.getMessage(), e); DorianInternalFault fault = new DorianInternalFault(); fault.setFaultString("Unexpected Database Error, could not determine if the user " + uid + " exists."); FaultHelper helper = new FaultHelper(fault); helper.addFaultCause(e); fault = (DorianInternalFault) helper.getFault(); throw fault; } finally { db.releaseConnection(c); } return exists; } public void clearDatabase() throws DorianInternalFault { this.buildDatabase(); try { db.update("drop TABLE " + IDP_USERS_TABLE); this.passwordSecurityManager.clearDatabase(); } catch (Exception e) { logError(e.getMessage(), e); DorianInternalFault fault = new DorianInternalFault(); fault.setFaultString("An unexpected database error occurred."); FaultHelper helper = new FaultHelper(fault); helper.addFaultCause(e); fault = (DorianInternalFault) helper.getFault(); throw fault; } } protected PasswordSecurityManager getPasswordSecurityManager() { return passwordSecurityManager; } }