From bd58ceccd8d08a2484384a7eef6ef3c681a1e188 Mon Sep 17 00:00:00 2001 From: Hugo Trippaers Date: Mon, 29 Oct 2012 18:02:34 +0100 Subject: [PATCH] Summary: Make the authenticator responsible for encoding the password and add a SHA256 salted authenticator The authenticators now have an encode function that cloudstack will use to encode the user supplied password before storing it in the database. This makes it easier to add other authenticators with other hashing algorithms. The requires a two step approach to creating the admin account at first start as the authenticators are only present in the management-server component locator. The SHA256 salted authenticator make use of this new system and adds a hashing algorithm based on SHA256 with a salt. This type of hash is far less susceptible to rainbow table attacks. To make use of these new features the users password will be sent over the wire just as he typed it and it will be transformed into a hash on the server and compared with the stored password. This means that the hash will not go over the wire anymore. The default authenticator in components.xml is still set to md5 for backwards compatibility. For new installations the sha256 could be enabled. --- client/pom.xml | 5 + client/tomcatconf/components.xml.in | 1 + plugins/pom.xml | 1 + .../server/auth/LDAPUserAuthenticator.java | 17 +++ .../server/auth/MD5UserAuthenticator.java | 51 ++++---- .../auth/PlainTextUserAuthenticator.java | 6 + .../user-authenticators/sha256salted/pom.xml | 29 +++++ .../auth/SHA256SaltedUserAuthenticator.java | 122 ++++++++++++++++++ .../server/auth/test/AuthenticatorTest.java | 46 +++++++ .../cloud/server/ConfigurationServerImpl.java | 30 ++--- .../com/cloud/server/ManagementServer.java | 2 + .../cloud/server/ManagementServerImpl.java | 33 +++++ .../cloud/server/auth/UserAuthenticator.java | 6 + .../cloud/servlet/CloudStartupServlet.java | 1 + .../com/cloud/user/AccountManagerImpl.java | 28 +++- ui/scripts/sharedFunctions.js | 4 +- 16 files changed, 331 insertions(+), 51 deletions(-) create mode 100644 plugins/user-authenticators/sha256salted/pom.xml create mode 100644 plugins/user-authenticators/sha256salted/src/com/cloud/server/auth/SHA256SaltedUserAuthenticator.java create mode 100644 plugins/user-authenticators/sha256salted/test/src/com/cloud/server/auth/test/AuthenticatorTest.java diff --git a/client/pom.xml b/client/pom.xml index c3a048604b1..6e13cc7ada9 100644 --- a/client/pom.xml +++ b/client/pom.xml @@ -40,6 +40,11 @@ cloud-plugin-user-authenticator-plaintext ${project.version} + + org.apache.cloudstack + cloud-plugin-user-authenticator-sha256salted + ${project.version} + org.apache.cloudstack cloud-plugin-network-nvp diff --git a/client/tomcatconf/components.xml.in b/client/tomcatconf/components.xml.in index 2953eb781a6..5957b61c0fb 100755 --- a/client/tomcatconf/components.xml.in +++ b/client/tomcatconf/components.xml.in @@ -109,6 +109,7 @@ under the License. + diff --git a/plugins/pom.xml b/plugins/pom.xml index dbdea24e17b..2009302423e 100644 --- a/plugins/pom.xml +++ b/plugins/pom.xml @@ -45,6 +45,7 @@ user-authenticators/ldap user-authenticators/md5 user-authenticators/plain-text + user-authenticators/sha256salted diff --git a/plugins/user-authenticators/ldap/src/com/cloud/server/auth/LDAPUserAuthenticator.java b/plugins/user-authenticators/ldap/src/com/cloud/server/auth/LDAPUserAuthenticator.java index 7c6e52f6659..43874f61cb7 100644 --- a/plugins/user-authenticators/ldap/src/com/cloud/server/auth/LDAPUserAuthenticator.java +++ b/plugins/user-authenticators/ldap/src/com/cloud/server/auth/LDAPUserAuthenticator.java @@ -15,6 +15,8 @@ // package com.cloud.server.auth; +import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; import java.util.HashMap; import java.util.Hashtable; import java.util.Map; @@ -31,6 +33,7 @@ import javax.naming.directory.SearchControls; import javax.naming.directory.SearchResult; import org.apache.log4j.Logger; +import org.bouncycastle.util.encoders.Base64; import com.cloud.api.ApiConstants.LDAPParams; import com.cloud.configuration.Config; @@ -40,6 +43,7 @@ import com.cloud.user.UserAccount; import com.cloud.user.dao.UserAccountDao; import com.cloud.utils.component.ComponentLocator; import com.cloud.utils.crypt.DBEncryptionUtil; +import com.cloud.utils.exception.CloudRuntimeException; @Local(value={UserAuthenticator.class}) @@ -159,4 +163,17 @@ public class LDAPUserAuthenticator extends DefaultUserAuthenticator { _userAccountDao = locator.getDao(UserAccountDao.class); return true; } + + @Override + public String encode(String password) { + // Password is not used, so set to a random string + try { + SecureRandom randomGen = SecureRandom.getInstance("SHA1PRNG"); + byte bytes[] = new byte[20]; + randomGen.nextBytes(bytes); + return Base64.encode(bytes).toString(); + } catch (NoSuchAlgorithmException e) { + throw new CloudRuntimeException("Failed to generate random password",e); + } + } } diff --git a/plugins/user-authenticators/md5/src/com/cloud/server/auth/MD5UserAuthenticator.java b/plugins/user-authenticators/md5/src/com/cloud/server/auth/MD5UserAuthenticator.java index f4b6f021f3b..b0cf0b03cd6 100644 --- a/plugins/user-authenticators/md5/src/com/cloud/server/auth/MD5UserAuthenticator.java +++ b/plugins/user-authenticators/md5/src/com/cloud/server/auth/MD5UserAuthenticator.java @@ -15,6 +15,9 @@ package com.cloud.server.auth; +import java.math.BigInteger; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; import java.util.Map; import javax.ejb.Local; @@ -26,6 +29,7 @@ import com.cloud.server.ManagementServer; import com.cloud.user.UserAccount; import com.cloud.user.dao.UserAccountDao; import com.cloud.utils.component.ComponentLocator; +import com.cloud.utils.exception.CloudRuntimeException; /** * Simple UserAuthenticator that performs a MD5 hash of the password before @@ -49,31 +53,7 @@ public class MD5UserAuthenticator extends DefaultUserAuthenticator { return false; } - /** - MessageDigest md5; - try { - md5 = MessageDigest.getInstance("MD5"); - } catch (NoSuchAlgorithmException e) { - throw new CloudRuntimeException("Error", e); - } - md5.reset(); - BigInteger pwInt = new BigInteger(1, md5.digest(password.getBytes())); - - // make sure our MD5 hash value is 32 digits long... - StringBuffer sb = new StringBuffer(); - String pwStr = pwInt.toString(16); - int padding = 32 - pwStr.length(); - for (int i = 0; i < padding; i++) { - sb.append('0'); - } - sb.append(pwStr); - **/ - - // Will: The MD5Authenticator is now a straight pass-through comparison of the - // the passwords because we will not assume that the password passed in has - // already been MD5 hashed. I am keeping the above code in case this requirement changes - // or people need examples of how to MD5 hash passwords in java. - if (!user.getPassword().equals(password)) { + if (!user.getPassword().equals(encode(password))) { s_logger.debug("Password does not match"); return false; } @@ -87,4 +67,25 @@ public class MD5UserAuthenticator extends DefaultUserAuthenticator { _userAccountDao = locator.getDao(UserAccountDao.class); return true; } + + @Override + public String encode(String password) { + MessageDigest md5 = null; + try { + md5 = MessageDigest.getInstance("MD5"); + } catch (NoSuchAlgorithmException e) { + throw new CloudRuntimeException("Unable to hash password", e); + } + + md5.reset(); + BigInteger pwInt = new BigInteger(1, md5.digest(password.getBytes())); + String pwStr = pwInt.toString(16); + int padding = 32 - pwStr.length(); + StringBuffer sb = new StringBuffer(); + for (int i = 0; i < padding; i++) { + sb.append('0'); // make sure the MD5 password is 32 digits long + } + sb.append(pwStr); + return sb.toString(); + } } diff --git a/plugins/user-authenticators/plain-text/src/com/cloud/server/auth/PlainTextUserAuthenticator.java b/plugins/user-authenticators/plain-text/src/com/cloud/server/auth/PlainTextUserAuthenticator.java index 006daf98e9b..59e12e50048 100644 --- a/plugins/user-authenticators/plain-text/src/com/cloud/server/auth/PlainTextUserAuthenticator.java +++ b/plugins/user-authenticators/plain-text/src/com/cloud/server/auth/PlainTextUserAuthenticator.java @@ -87,4 +87,10 @@ public class PlainTextUserAuthenticator extends DefaultUserAuthenticator { _userAccountDao = locator.getDao(UserAccountDao.class); return true; } + + @Override + public String encode(String password) { + // Plaintext so no encoding at all + return password; + } } diff --git a/plugins/user-authenticators/sha256salted/pom.xml b/plugins/user-authenticators/sha256salted/pom.xml new file mode 100644 index 00000000000..3f530f76e17 --- /dev/null +++ b/plugins/user-authenticators/sha256salted/pom.xml @@ -0,0 +1,29 @@ + + + 4.0.0 + cloud-plugin-user-authenticator-sha256salted + Apache CloudStack Plugin - User Authenticator SHA256 Salted + + org.apache.cloudstack + cloudstack-plugins + 4.1.0-SNAPSHOT + ../../pom.xml + + diff --git a/plugins/user-authenticators/sha256salted/src/com/cloud/server/auth/SHA256SaltedUserAuthenticator.java b/plugins/user-authenticators/sha256salted/src/com/cloud/server/auth/SHA256SaltedUserAuthenticator.java new file mode 100644 index 00000000000..26c33a5a9ec --- /dev/null +++ b/plugins/user-authenticators/sha256salted/src/com/cloud/server/auth/SHA256SaltedUserAuthenticator.java @@ -0,0 +1,122 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package com.cloud.server.auth; + +import java.io.UnsupportedEncodingException; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; +import java.util.Map; + +import javax.ejb.Local; +import javax.naming.ConfigurationException; + +import org.apache.log4j.Logger; +import org.bouncycastle.util.encoders.Base64; + +import com.cloud.server.ManagementServer; +import com.cloud.servlet.CloudStartupServlet; +import com.cloud.user.UserAccount; +import com.cloud.user.dao.UserAccountDao; +import com.cloud.utils.component.ComponentLocator; +import com.cloud.utils.component.Inject; +import com.cloud.utils.exception.CloudRuntimeException; + +@Local(value={UserAuthenticator.class}) +public class SHA256SaltedUserAuthenticator extends DefaultUserAuthenticator { + public static final Logger s_logger = Logger.getLogger(SHA256SaltedUserAuthenticator.class); + + @Inject + private UserAccountDao _userAccountDao; + private static int s_saltlen = 20; + + public boolean configure(String name, Map params) + throws ConfigurationException { + super.configure(name, params); + return true; + } + + /* (non-Javadoc) + * @see com.cloud.server.auth.UserAuthenticator#authenticate(java.lang.String, java.lang.String, java.lang.Long, java.util.Map) + */ + @Override + public boolean authenticate(String username, String password, + Long domainId, Map requestParameters) { + if (s_logger.isDebugEnabled()) { + s_logger.debug("Retrieving user: " + username); + } + UserAccount user = _userAccountDao.getUserAccount(username, domainId); + if (user == null) { + s_logger.debug("Unable to find user with " + username + " in domain " + domainId); + return false; + } + + try { + String storedPassword[] = user.getPassword().split(":"); + if (storedPassword.length != 2) { + s_logger.warn("The stored password for " + username + " isn't in the right format for this authenticator"); + return false; + } + byte salt[] = Base64.decode(storedPassword[0]); + String hashedPassword = encode(password, salt); + return storedPassword[1].equals(hashedPassword); + } catch (NoSuchAlgorithmException e) { + throw new CloudRuntimeException("Unable to hash password", e); + } catch (UnsupportedEncodingException e) { + throw new CloudRuntimeException("Unable to hash password", e); + } + } + + /* (non-Javadoc) + * @see com.cloud.server.auth.UserAuthenticator#encode(java.lang.String) + */ + @Override + public String encode(String password) { + // 1. Generate the salt + SecureRandom randomGen; + try { + randomGen = SecureRandom.getInstance("SHA1PRNG"); + + byte salt[] = new byte[s_saltlen]; + randomGen.nextBytes(salt); + + String saltString = new String(Base64.encode(salt)); + String hashString = encode(password, salt); + + // 3. concatenate the two and return + return saltString + ":" + hashString; + } catch (NoSuchAlgorithmException e) { + throw new CloudRuntimeException("Unable to hash password", e); + } catch (UnsupportedEncodingException e) { + throw new CloudRuntimeException("Unable to hash password", e); + } + } + + public String encode(String password, byte[] salt) throws UnsupportedEncodingException, NoSuchAlgorithmException { + byte[] passwordBytes = password.getBytes("UTF-8"); + byte[] hashSource = new byte[passwordBytes.length + s_saltlen]; + System.arraycopy(passwordBytes, 0, hashSource, 0, passwordBytes.length); + System.arraycopy(salt, 0, hashSource, passwordBytes.length, s_saltlen); + + // 2. Hash the password with the salt + MessageDigest md = MessageDigest.getInstance("SHA-256"); + md.update(hashSource); + byte[] digest = md.digest(); + + return new String(Base64.encode(digest)); + } +} diff --git a/plugins/user-authenticators/sha256salted/test/src/com/cloud/server/auth/test/AuthenticatorTest.java b/plugins/user-authenticators/sha256salted/test/src/com/cloud/server/auth/test/AuthenticatorTest.java new file mode 100644 index 00000000000..cf990248f39 --- /dev/null +++ b/plugins/user-authenticators/sha256salted/test/src/com/cloud/server/auth/test/AuthenticatorTest.java @@ -0,0 +1,46 @@ +package src.com.cloud.server.auth.test; + +import static org.junit.Assert.*; + +import java.io.UnsupportedEncodingException; +import java.security.NoSuchAlgorithmException; +import java.util.Collections; + +import javax.naming.ConfigurationException; + +import org.bouncycastle.util.encoders.Base64; +import org.junit.Before; +import org.junit.Test; + +import com.cloud.server.auth.SHA256SaltedUserAuthenticator; + +public class AuthenticatorTest { + + @Before + public void setUp() throws Exception { + } + + @Test + public void testEncode() throws UnsupportedEncodingException, NoSuchAlgorithmException { + SHA256SaltedUserAuthenticator authenticator = + new SHA256SaltedUserAuthenticator(); + + try { + authenticator.configure("SHA256", Collections.emptyMap()); + } catch (ConfigurationException e) { + fail(e.toString()); + } + + String encodedPassword = authenticator.encode("password"); + + String storedPassword[] = encodedPassword.split(":"); + assertEquals ("hash must consist of two components", storedPassword.length, 2); + + byte salt[] = Base64.decode(storedPassword[0]); + String hashedPassword = authenticator.encode("password", salt); + + assertEquals("compare hashes", storedPassword[1], hashedPassword); + + } + +} diff --git a/server/src/com/cloud/server/ConfigurationServerImpl.java b/server/src/com/cloud/server/ConfigurationServerImpl.java index 3368c9ba116..904e8c59f6e 100755 --- a/server/src/com/cloud/server/ConfigurationServerImpl.java +++ b/server/src/com/cloud/server/ConfigurationServerImpl.java @@ -32,6 +32,7 @@ import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; +import java.util.Enumeration; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -85,6 +86,7 @@ import com.cloud.offerings.NetworkOfferingServiceMapVO; import com.cloud.offerings.NetworkOfferingVO; import com.cloud.offerings.dao.NetworkOfferingDao; import com.cloud.offerings.dao.NetworkOfferingServiceMapDao; +import com.cloud.server.auth.UserAuthenticator; import com.cloud.service.ServiceOfferingVO; import com.cloud.service.dao.ServiceOfferingDao; import com.cloud.storage.DiskOfferingVO; @@ -96,6 +98,7 @@ import com.cloud.user.User; import com.cloud.user.dao.AccountDao; import com.cloud.utils.PasswordGenerator; import com.cloud.utils.PropertiesUtil; +import com.cloud.utils.component.Adapters; import com.cloud.utils.component.ComponentLocator; import com.cloud.utils.crypt.DBEncryptionUtil; import com.cloud.utils.db.DB; @@ -342,30 +345,13 @@ public class ConfigurationServerImpl implements ConfigurationServer { } catch (SQLException ex) { } - // insert admin user + // insert admin user, but leave the account disabled until we set a + // password with the user authenticator long id = 2; String username = "admin"; String firstname = "admin"; String lastname = "cloud"; - String password = "password"; - - MessageDigest md5 = null; - try { - md5 = MessageDigest.getInstance("MD5"); - } catch (NoSuchAlgorithmException e) { - return; - } - - md5.reset(); - BigInteger pwInt = new BigInteger(1, md5.digest(password.getBytes())); - String pwStr = pwInt.toString(16); - int padding = 32 - pwStr.length(); - StringBuffer sb = new StringBuffer(); - for (int i = 0; i < padding; i++) { - sb.append('0'); // make sure the MD5 password is 32 digits long - } - sb.append(pwStr); - + // create an account for the admin user first insertSql = "INSERT INTO `cloud`.`account` (id, account_name, type, domain_id) VALUES (" + id + ", '" + username + "', '1', '1')"; txn = Transaction.currentTxn(); @@ -376,8 +362,8 @@ public class ConfigurationServerImpl implements ConfigurationServer { } // now insert the user - insertSql = "INSERT INTO `cloud`.`user` (id, username, password, account_id, firstname, lastname, created) " + - "VALUES (" + id + ",'" + username + "','" + sb.toString() + "', 2, '" + firstname + "','" + lastname + "',now())"; + insertSql = "INSERT INTO `cloud`.`user` (id, username, account_id, firstname, lastname, created, state) " + + "VALUES (" + id + ",'" + username + "', 2, '" + firstname + "','" + lastname + "',now(), 'disabled')"; txn = Transaction.currentTxn(); try { diff --git a/server/src/com/cloud/server/ManagementServer.java b/server/src/com/cloud/server/ManagementServer.java index 473b0ee9b3a..91f82f874d5 100755 --- a/server/src/com/cloud/server/ManagementServer.java +++ b/server/src/com/cloud/server/ManagementServer.java @@ -95,4 +95,6 @@ public interface ManagementServer extends ManagementService { Pair, Integer> searchForStoragePools(Criteria c); String getHashKey(); + + public void enableAdminUser(String password); } diff --git a/server/src/com/cloud/server/ManagementServerImpl.java b/server/src/com/cloud/server/ManagementServerImpl.java index a916eb69696..117be5797b0 100755 --- a/server/src/com/cloud/server/ManagementServerImpl.java +++ b/server/src/com/cloud/server/ManagementServerImpl.java @@ -177,6 +177,7 @@ import com.cloud.projects.Project.ListProjectResourcesCriteria; import com.cloud.projects.ProjectManager; import com.cloud.resource.ResourceManager; import com.cloud.server.ResourceTag.TaggedResourceType; +import com.cloud.server.auth.UserAuthenticator; import com.cloud.service.ServiceOfferingVO; import com.cloud.service.dao.ServiceOfferingDao; import com.cloud.storage.DiskOfferingVO; @@ -215,7 +216,9 @@ import com.cloud.user.AccountVO; import com.cloud.user.SSHKeyPair; import com.cloud.user.SSHKeyPairVO; import com.cloud.user.User; +import com.cloud.user.UserAccount; import com.cloud.user.UserContext; +import com.cloud.user.UserVO; import com.cloud.user.dao.AccountDao; import com.cloud.user.dao.SSHKeyPairDao; import com.cloud.user.dao.UserDao; @@ -338,6 +341,8 @@ public class ManagementServerImpl implements ManagementServer { private final StatsCollector _statsCollector; private final Map _availableIdsMap; + + private Adapters _userAuthenticators; private String _hashKey = null; @@ -417,6 +422,11 @@ public class ManagementServerImpl implements ManagementServer { for (String id : availableIds) { _availableIdsMap.put(id, true); } + + _userAuthenticators = locator.getAdapters(UserAuthenticator.class); + if (_userAuthenticators == null || !_userAuthenticators.isSet()) { + s_logger.error("Unable to find an user authenticator."); + } } protected Map getConfigs() { @@ -3587,5 +3597,28 @@ public class ManagementServerImpl implements ManagementServer { } } + + public void enableAdminUser(String password) { + String encodedPassword = null; + + UserVO adminUser = _userDao.getUser(2); + if (adminUser.getState() == Account.State.disabled) { + // This means its a new account, set the password using the authenticator + + for (Enumeration en = _userAuthenticators.enumeration(); en.hasMoreElements();) { + UserAuthenticator authenticator = en.nextElement(); + encodedPassword = authenticator.encode(password); + if (encodedPassword != null) { + break; + } + } + + adminUser.setPassword(encodedPassword); + adminUser.setState(Account.State.enabled); + _userDao.persist(adminUser); + s_logger.info("Admin user enabled"); + } + + } } diff --git a/server/src/com/cloud/server/auth/UserAuthenticator.java b/server/src/com/cloud/server/auth/UserAuthenticator.java index 725516c096f..95c4f0e4707 100644 --- a/server/src/com/cloud/server/auth/UserAuthenticator.java +++ b/server/src/com/cloud/server/auth/UserAuthenticator.java @@ -34,4 +34,10 @@ public interface UserAuthenticator extends Adapter { * @return true if the user has been successfully authenticated, false otherwise */ public boolean authenticate(String username, String password, Long domainId, Map requestParameters); + + /** + * @param password + * @return the encoded password + */ + public String encode(String password); } diff --git a/server/src/com/cloud/servlet/CloudStartupServlet.java b/server/src/com/cloud/servlet/CloudStartupServlet.java index c3e5a8235ce..9efb4ea5a8c 100755 --- a/server/src/com/cloud/servlet/CloudStartupServlet.java +++ b/server/src/com/cloud/servlet/CloudStartupServlet.java @@ -47,6 +47,7 @@ public class CloudStartupServlet extends HttpServlet implements ServletContextLi c.persistDefaultValues(); s_locator = ComponentLocator.getLocator(ManagementServer.Name); ManagementServer ms = (ManagementServer)ComponentLocator.getComponent(ManagementServer.Name); + ms.enableAdminUser("password"); ApiServer.initApiServer(ms.getApiConfig()); } catch (InvalidParameterValueException ipve) { s_logger.error("Exception starting management server ", ipve); diff --git a/server/src/com/cloud/user/AccountManagerImpl.java b/server/src/com/cloud/user/AccountManagerImpl.java index f1e606e76a1..0def0083f66 100755 --- a/server/src/com/cloud/user/AccountManagerImpl.java +++ b/server/src/com/cloud/user/AccountManagerImpl.java @@ -921,7 +921,18 @@ public class AccountManagerImpl implements AccountManager, AccountService, Manag } if (password != null) { - user.setPassword(password); + String encodedPassword = null; + for (Enumeration en = _userAuthenticators.enumeration(); en.hasMoreElements();) { + UserAuthenticator authenticator = en.nextElement(); + encodedPassword = authenticator.encode(password); + if (encodedPassword != null) { + break; + } + } + if (encodedPassword == null) { + throw new CloudRuntimeException("Failed to encode password"); + } + user.setPassword(encodedPassword); } if (email != null) { user.setEmail(email); @@ -1670,7 +1681,20 @@ public class AccountManagerImpl implements AccountManager, AccountService, Manag if (s_logger.isDebugEnabled()) { s_logger.debug("Creating user: " + userName + ", accountId: " + accountId + " timezone:" + timezone); } - UserVO user = _userDao.persist(new UserVO(accountId, userName, password, firstName, lastName, email, timezone)); + + String encodedPassword = null; + for (Enumeration en = _userAuthenticators.enumeration(); en.hasMoreElements();) { + UserAuthenticator authenticator = en.nextElement(); + encodedPassword = authenticator.encode(password); + if (encodedPassword != null) { + break; + } + } + if (encodedPassword == null) { + throw new CloudRuntimeException("Failed to encode password"); + } + + UserVO user = _userDao.persist(new UserVO(accountId, userName, encodedPassword, firstName, lastName, email, timezone)); return user; } diff --git a/ui/scripts/sharedFunctions.js b/ui/scripts/sharedFunctions.js index 5e187ed1b82..28b3bb9550f 100644 --- a/ui/scripts/sharedFunctions.js +++ b/ui/scripts/sharedFunctions.js @@ -37,8 +37,8 @@ var ERROR_INTERNET_CANNOT_CONNECT = 12029; var ERROR_VMOPS_ACCOUNT_ERROR = 531; // Default password is MD5 hashed. Set the following variable to false to disable this. -var md5Hashed = true; -var md5HashedLogin = true; +var md5Hashed = false; +var md5HashedLogin = false; //page size for API call (e.g."listXXXXXXX&pagesize=N" ) var pageSize = 20;