mirror of
https://github.com/apache/cloudstack.git
synced 2025-10-26 08:42:29 +01:00
CLOUDSTACK-1734: Make SHA1 default password encoding mechanism
Description: Making SHA256SALT the default encoding algorithm to encode passwords when creating/updating users. Introducing a new configurable list to allow admins to separately configure the order of preference for encoding and authentication schemes. Since passwords are now sent by clients as clear text, fixing the Plain text authenticator to check against the password passed in rather than its md5 digest.
This commit is contained in:
parent
58c962ef15
commit
2dbdc46337
@ -63,7 +63,7 @@ public class CreateAccountCmd extends BaseCmd {
|
|||||||
@Parameter(name=ApiConstants.LASTNAME, type=CommandType.STRING, required=true, description="lastname")
|
@Parameter(name=ApiConstants.LASTNAME, type=CommandType.STRING, required=true, description="lastname")
|
||||||
private String lastName;
|
private String lastName;
|
||||||
|
|
||||||
@Parameter(name=ApiConstants.PASSWORD, type=CommandType.STRING, required=true, description="Hashed password (Default is MD5). If you wish to use any other hashing algorithm, you would need to write a custom authentication adapter See Docs section.")
|
@Parameter(name=ApiConstants.PASSWORD, type=CommandType.STRING, required=true, description="Clear text password (Default hashed to SHA256SALT). If you wish to use any other hashing algorithm, you would need to write a custom authentication adapter See Docs section.")
|
||||||
private String password;
|
private String password;
|
||||||
|
|
||||||
@Parameter(name=ApiConstants.TIMEZONE, type=CommandType.STRING, description="Specifies a timezone for this command. For more information on the timezone parameter, see Time Zone Format.")
|
@Parameter(name=ApiConstants.TIMEZONE, type=CommandType.STRING, description="Specifies a timezone for this command. For more information on the timezone parameter, see Time Zone Format.")
|
||||||
|
|||||||
@ -56,7 +56,7 @@ public class CreateUserCmd extends BaseCmd {
|
|||||||
@Parameter(name=ApiConstants.LASTNAME, type=CommandType.STRING, required=true, description="lastname")
|
@Parameter(name=ApiConstants.LASTNAME, type=CommandType.STRING, required=true, description="lastname")
|
||||||
private String lastname;
|
private String lastname;
|
||||||
|
|
||||||
@Parameter(name=ApiConstants.PASSWORD, type=CommandType.STRING, required=true, description="Hashed password (Default is MD5). If you wish to use any other hashing algorithm, you would need to write a custom authentication adapter See Docs section.")
|
@Parameter(name=ApiConstants.PASSWORD, type=CommandType.STRING, required=true, description="Clear text password (Default hashed to SHA256SALT). If you wish to use any other hashing algorithm, you would need to write a custom authentication adapter See Docs section.")
|
||||||
private String password;
|
private String password;
|
||||||
|
|
||||||
@Parameter(name=ApiConstants.TIMEZONE, type=CommandType.STRING, description="Specifies a timezone for this command. For more information on the timezone parameter, see Time Zone Format.")
|
@Parameter(name=ApiConstants.TIMEZONE, type=CommandType.STRING, description="Specifies a timezone for this command. For more information on the timezone parameter, see Time Zone Format.")
|
||||||
|
|||||||
@ -59,7 +59,7 @@ public class UpdateUserCmd extends BaseCmd {
|
|||||||
@Parameter(name=ApiConstants.LASTNAME, type=CommandType.STRING, description="last name")
|
@Parameter(name=ApiConstants.LASTNAME, type=CommandType.STRING, description="last name")
|
||||||
private String lastname;
|
private String lastname;
|
||||||
|
|
||||||
@Parameter(name=ApiConstants.PASSWORD, type=CommandType.STRING, description="Hashed password (default is MD5). If you wish to use any other hasing algorithm, you would need to write a custom authentication adapter")
|
@Parameter(name=ApiConstants.PASSWORD, type=CommandType.STRING, description="Clear text password (default hashed to SHA256SALT). If you wish to use any other hasing algorithm, you would need to write a custom authentication adapter")
|
||||||
private String password;
|
private String password;
|
||||||
|
|
||||||
@Parameter(name=ApiConstants.SECRET_KEY, type=CommandType.STRING, description="The secret key for the user. Must be specified with userApiKey")
|
@Parameter(name=ApiConstants.SECRET_KEY, type=CommandType.STRING, description="The secret key for the user. Must be specified with userApiKey")
|
||||||
|
|||||||
@ -379,6 +379,60 @@
|
|||||||
<bean id="LDAPUserAuthenticator" class="com.cloud.server.auth.LDAPUserAuthenticator">
|
<bean id="LDAPUserAuthenticator" class="com.cloud.server.auth.LDAPUserAuthenticator">
|
||||||
<property name="name" value="LDAP"/>
|
<property name="name" value="LDAP"/>
|
||||||
</bean>
|
</bean>
|
||||||
|
<bean id="SHA256SaltedUserAuthenticator" class="com.cloud.server.auth.SHA256SaltedUserAuthenticator">
|
||||||
|
<property name="name" value="SHA256SALT"/>
|
||||||
|
</bean>
|
||||||
|
<bean id="PlainTextUserAuthenticator" class="com.cloud.server.auth.PlainTextUserAuthenticator">
|
||||||
|
<property name="name" value="PLAINTEXT"/>
|
||||||
|
</bean>
|
||||||
|
|
||||||
|
<bean id="accountManagerImpl" class="com.cloud.user.AccountManagerImpl" >
|
||||||
|
<property name="UserAuthenticators">
|
||||||
|
<list>
|
||||||
|
<ref bean="SHA256SaltedUserAuthenticator"/>
|
||||||
|
<ref bean="MD5UserAuthenticator"/>
|
||||||
|
<ref bean="LDAPUserAuthenticator"/>
|
||||||
|
<ref bean="PlainTextUserAuthenticator"/>
|
||||||
|
</list>
|
||||||
|
</property>
|
||||||
|
<property name="UserPasswordEncoders">
|
||||||
|
<list>
|
||||||
|
<ref bean="SHA256SaltedUserAuthenticator"/>
|
||||||
|
<ref bean="MD5UserAuthenticator"/>
|
||||||
|
<ref bean="LDAPUserAuthenticator"/>
|
||||||
|
<ref bean="PlainTextUserAuthenticator"/>
|
||||||
|
</list>
|
||||||
|
</property>
|
||||||
|
<property name="SecurityCheckers">
|
||||||
|
<list>
|
||||||
|
<ref bean="domainChecker"/>
|
||||||
|
</list>
|
||||||
|
</property>
|
||||||
|
</bean>
|
||||||
|
|
||||||
|
<bean id="managementServerImpl" class ="com.cloud.server.ManagementServerImpl">
|
||||||
|
<property name="UserAuthenticators">
|
||||||
|
<list>
|
||||||
|
<ref bean="SHA256SaltedUserAuthenticator"/>
|
||||||
|
<ref bean="MD5UserAuthenticator"/>
|
||||||
|
<ref bean="LDAPUserAuthenticator"/>
|
||||||
|
<ref bean="PlainTextUserAuthenticator"/>
|
||||||
|
</list>
|
||||||
|
</property>
|
||||||
|
<property name="UserPasswordEncoders">
|
||||||
|
<list>
|
||||||
|
<ref bean="SHA256SaltedUserAuthenticator"/>
|
||||||
|
<ref bean="MD5UserAuthenticator"/>
|
||||||
|
<ref bean="LDAPUserAuthenticator"/>
|
||||||
|
<ref bean="PlainTextUserAuthenticator"/>
|
||||||
|
</list>
|
||||||
|
</property>
|
||||||
|
<property name="HostAllocators">
|
||||||
|
<list>
|
||||||
|
<ref bean="FirstFitRouting"/>
|
||||||
|
</list>
|
||||||
|
</property>
|
||||||
|
</bean>
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
Network Elements
|
Network Elements
|
||||||
|
|||||||
@ -40,34 +40,6 @@
|
|||||||
<!--
|
<!--
|
||||||
Managers & pluggable adapters configuration under OSS deployment
|
Managers & pluggable adapters configuration under OSS deployment
|
||||||
-->
|
-->
|
||||||
<bean id="accountManagerImpl" class="com.cloud.user.AccountManagerImpl" >
|
|
||||||
<property name="UserAuthenticators">
|
|
||||||
<list>
|
|
||||||
<ref bean="MD5UserAuthenticator"/>
|
|
||||||
<ref bean="LDAPUserAuthenticator"/>
|
|
||||||
</list>
|
|
||||||
</property>
|
|
||||||
<property name="SecurityCheckers">
|
|
||||||
<list>
|
|
||||||
<ref bean="domainChecker"/>
|
|
||||||
</list>
|
|
||||||
</property>
|
|
||||||
</bean>
|
|
||||||
|
|
||||||
<bean id="managementServerImpl" class ="com.cloud.server.ManagementServerImpl">
|
|
||||||
<property name="UserAuthenticators">
|
|
||||||
<list>
|
|
||||||
<ref bean="MD5UserAuthenticator"/>
|
|
||||||
<ref bean="LDAPUserAuthenticator"/>
|
|
||||||
</list>
|
|
||||||
</property>
|
|
||||||
<property name="HostAllocators">
|
|
||||||
<list>
|
|
||||||
<ref bean="FirstFitRouting"/>
|
|
||||||
</list>
|
|
||||||
</property>
|
|
||||||
</bean>
|
|
||||||
|
|
||||||
<bean id="storageManagerImpl" class="com.cloud.storage.StorageManagerImpl">
|
<bean id="storageManagerImpl" class="com.cloud.storage.StorageManagerImpl">
|
||||||
<property name="StoragePoolAllocators">
|
<property name="StoragePoolAllocators">
|
||||||
<list>
|
<list>
|
||||||
|
|||||||
@ -131,34 +131,6 @@
|
|||||||
<!--
|
<!--
|
||||||
Managers & pluggable adapters configuration under non-OSS deployment
|
Managers & pluggable adapters configuration under non-OSS deployment
|
||||||
-->
|
-->
|
||||||
<bean id="accountManagerImpl" class="com.cloud.user.AccountManagerImpl" >
|
|
||||||
<property name="UserAuthenticators">
|
|
||||||
<list>
|
|
||||||
<ref bean="MD5UserAuthenticator"/>
|
|
||||||
<ref bean="LDAPUserAuthenticator"/>
|
|
||||||
</list>
|
|
||||||
</property>
|
|
||||||
<property name="SecurityCheckers">
|
|
||||||
<list>
|
|
||||||
<ref bean="domainChecker"/>
|
|
||||||
</list>
|
|
||||||
</property>
|
|
||||||
</bean>
|
|
||||||
|
|
||||||
<bean id="managementServerImpl" class ="com.cloud.server.ManagementServerImpl">
|
|
||||||
<property name="UserAuthenticators">
|
|
||||||
<list>
|
|
||||||
<ref bean="MD5UserAuthenticator"/>
|
|
||||||
<ref bean="LDAPUserAuthenticator"/>
|
|
||||||
</list>
|
|
||||||
</property>
|
|
||||||
<property name="HostAllocators">
|
|
||||||
<list>
|
|
||||||
<ref bean="FirstFitRouting"/>
|
|
||||||
</list>
|
|
||||||
</property>
|
|
||||||
</bean>
|
|
||||||
|
|
||||||
<bean id="storageManagerImpl" class="com.cloud.storage.StorageManagerImpl">
|
<bean id="storageManagerImpl" class="com.cloud.storage.StorageManagerImpl">
|
||||||
<property name="StoragePoolAllocators">
|
<property name="StoragePoolAllocators">
|
||||||
<list>
|
<list>
|
||||||
|
|||||||
@ -36,7 +36,7 @@ INSERT INTO `cloud`.`user` (id, uuid, username, password, account_id, firstname,
|
|||||||
-- Add system user with encrypted password=password
|
-- Add system user with encrypted password=password
|
||||||
INSERT INTO `cloud`.`user` (id, uuid, username, password, account_id, firstname,
|
INSERT INTO `cloud`.`user` (id, uuid, username, password, account_id, firstname,
|
||||||
lastname, email, state, created) VALUES (2, UUID(), 'admin', '5f4dcc3b5aa765d61d8327deb882cf99',
|
lastname, email, state, created) VALUES (2, UUID(), 'admin', '5f4dcc3b5aa765d61d8327deb882cf99',
|
||||||
'2', 'Admin', 'User', 'admin@mailprovider.com', 'enabled', NOW());
|
'2', 'Admin', 'User', 'admin@mailprovider.com', 'disabled', NOW());
|
||||||
|
|
||||||
-- Add configurations
|
-- Add configurations
|
||||||
INSERT INTO `cloud`.`configuration` (category, instance, component, name, value)
|
INSERT INTO `cloud`.`configuration` (category, instance, component, name, value)
|
||||||
|
|||||||
@ -151,7 +151,10 @@ public class LDAPUserAuthenticator extends DefaultUserAuthenticator {
|
|||||||
@Override
|
@Override
|
||||||
public boolean configure(String name, Map<String, Object> params)
|
public boolean configure(String name, Map<String, Object> params)
|
||||||
throws ConfigurationException {
|
throws ConfigurationException {
|
||||||
super.configure(name, params);
|
if (name == null) {
|
||||||
|
name = "LDAP";
|
||||||
|
}
|
||||||
|
super.configure(name, params);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -59,8 +59,12 @@ public class MD5UserAuthenticator extends DefaultUserAuthenticator {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean configure(String name, Map<String, Object> params)
|
public boolean configure(String name, Map<String, Object> params)
|
||||||
throws ConfigurationException {
|
throws ConfigurationException {
|
||||||
|
if(name == null) {
|
||||||
|
name = "MD5";
|
||||||
|
}
|
||||||
super.configure(name, params);
|
super.configure(name, params);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -28,7 +28,6 @@ import org.apache.log4j.Logger;
|
|||||||
|
|
||||||
import com.cloud.user.UserAccount;
|
import com.cloud.user.UserAccount;
|
||||||
import com.cloud.user.dao.UserAccountDao;
|
import com.cloud.user.dao.UserAccountDao;
|
||||||
|
|
||||||
import com.cloud.utils.exception.CloudRuntimeException;
|
import com.cloud.utils.exception.CloudRuntimeException;
|
||||||
|
|
||||||
|
|
||||||
@ -43,45 +42,26 @@ public class PlainTextUserAuthenticator extends DefaultUserAuthenticator {
|
|||||||
if (s_logger.isDebugEnabled()) {
|
if (s_logger.isDebugEnabled()) {
|
||||||
s_logger.debug("Retrieving user: " + username);
|
s_logger.debug("Retrieving user: " + username);
|
||||||
}
|
}
|
||||||
|
|
||||||
UserAccount user = _userAccountDao.getUserAccount(username, domainId);
|
UserAccount user = _userAccountDao.getUserAccount(username, domainId);
|
||||||
if (user == null) {
|
if (user == null) {
|
||||||
s_logger.debug("Unable to find user with " + username + " in domain " + domainId);
|
s_logger.debug("Unable to find user with " + username + " in domain " + domainId);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!user.getPassword().equals(password)) {
|
||||||
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(sb.toString())) {
|
|
||||||
s_logger.debug("Password does not match");
|
s_logger.debug("Password does not match");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean configure(String name, Map<String, Object> params)
|
public boolean configure(String name, Map<String, Object> params)
|
||||||
throws ConfigurationException {
|
throws ConfigurationException {
|
||||||
|
if (name == null) {
|
||||||
|
name = "PLAINTEXT";
|
||||||
|
}
|
||||||
super.configure(name, params);
|
super.configure(name, params);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -44,6 +44,9 @@ public class SHA256SaltedUserAuthenticator extends DefaultUserAuthenticator {
|
|||||||
@Override
|
@Override
|
||||||
public boolean configure(String name, Map<String, Object> params)
|
public boolean configure(String name, Map<String, Object> params)
|
||||||
throws ConfigurationException {
|
throws ConfigurationException {
|
||||||
|
if (name == null) {
|
||||||
|
name = "SHA256SALT";
|
||||||
|
}
|
||||||
super.configure(name, params);
|
super.configure(name, params);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -457,7 +457,8 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe
|
|||||||
|
|
||||||
private Map<String, Boolean> _availableIdsMap;
|
private Map<String, Boolean> _availableIdsMap;
|
||||||
|
|
||||||
List<UserAuthenticator> _userAuthenticators;
|
private List<UserAuthenticator> _userAuthenticators;
|
||||||
|
private List<UserAuthenticator> _userPasswordEncoders;
|
||||||
|
|
||||||
@Inject ClusterManager _clusterMgr;
|
@Inject ClusterManager _clusterMgr;
|
||||||
private String _hashKey = null;
|
private String _hashKey = null;
|
||||||
@ -473,7 +474,15 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe
|
|||||||
public void setUserAuthenticators(List<UserAuthenticator> authenticators) {
|
public void setUserAuthenticators(List<UserAuthenticator> authenticators) {
|
||||||
_userAuthenticators = authenticators;
|
_userAuthenticators = authenticators;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<UserAuthenticator> getUserPasswordEncoders() {
|
||||||
|
return _userPasswordEncoders;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUserPasswordEncoders(List<UserAuthenticator> encoders) {
|
||||||
|
_userPasswordEncoders = encoders;
|
||||||
|
}
|
||||||
|
|
||||||
public List<HostAllocator> getHostAllocators() {
|
public List<HostAllocator> getHostAllocators() {
|
||||||
return _hostAllocators;
|
return _hostAllocators;
|
||||||
}
|
}
|
||||||
@ -3342,7 +3351,7 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe
|
|||||||
// This means its a new account, set the password using the
|
// This means its a new account, set the password using the
|
||||||
// authenticator
|
// authenticator
|
||||||
|
|
||||||
for (UserAuthenticator authenticator: _userAuthenticators) {
|
for (UserAuthenticator authenticator: _userPasswordEncoders) {
|
||||||
encodedPassword = authenticator.encode(password);
|
encodedPassword = authenticator.encode(password);
|
||||||
if (encodedPassword != null) {
|
if (encodedPassword != null) {
|
||||||
break;
|
break;
|
||||||
|
|||||||
@ -222,6 +222,7 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
|
|||||||
@Inject VolumeManager volumeMgr;
|
@Inject VolumeManager volumeMgr;
|
||||||
|
|
||||||
private List<UserAuthenticator> _userAuthenticators;
|
private List<UserAuthenticator> _userAuthenticators;
|
||||||
|
List<UserAuthenticator> _userPasswordEncoders;
|
||||||
|
|
||||||
private final ScheduledExecutorService _executor = Executors.newScheduledThreadPool(1, new NamedThreadFactory("AccountChecker"));
|
private final ScheduledExecutorService _executor = Executors.newScheduledThreadPool(1, new NamedThreadFactory("AccountChecker"));
|
||||||
|
|
||||||
@ -241,7 +242,15 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
|
|||||||
public void setUserAuthenticators(List<UserAuthenticator> authenticators) {
|
public void setUserAuthenticators(List<UserAuthenticator> authenticators) {
|
||||||
_userAuthenticators = authenticators;
|
_userAuthenticators = authenticators;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<UserAuthenticator> getUserPasswordEncoders() {
|
||||||
|
return _userPasswordEncoders;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUserPasswordEncoders(List<UserAuthenticator> encoders) {
|
||||||
|
_userPasswordEncoders = encoders;
|
||||||
|
}
|
||||||
|
|
||||||
public List<SecurityChecker> getSecurityCheckers() {
|
public List<SecurityChecker> getSecurityCheckers() {
|
||||||
return _securityCheckers;
|
return _securityCheckers;
|
||||||
}
|
}
|
||||||
@ -947,7 +956,7 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
|
|||||||
|
|
||||||
if (password != null) {
|
if (password != null) {
|
||||||
String encodedPassword = null;
|
String encodedPassword = null;
|
||||||
for (Iterator<UserAuthenticator> en = _userAuthenticators.iterator(); en.hasNext();) {
|
for (Iterator<UserAuthenticator> en = _userPasswordEncoders.iterator(); en.hasNext();) {
|
||||||
UserAuthenticator authenticator = en.next();
|
UserAuthenticator authenticator = en.next();
|
||||||
encodedPassword = authenticator.encode(password);
|
encodedPassword = authenticator.encode(password);
|
||||||
if (encodedPassword != null) {
|
if (encodedPassword != null) {
|
||||||
@ -1733,7 +1742,7 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
|
|||||||
}
|
}
|
||||||
|
|
||||||
String encodedPassword = null;
|
String encodedPassword = null;
|
||||||
for (UserAuthenticator authenticator : _userAuthenticators) {
|
for (UserAuthenticator authenticator : _userPasswordEncoders) {
|
||||||
encodedPassword = authenticator.encode(password);
|
encodedPassword = authenticator.encode(password);
|
||||||
if (encodedPassword != null) {
|
if (encodedPassword != null) {
|
||||||
break;
|
break;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user