You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by ah...@apache.org on 2012/09/13 20:43:49 UTC

[42/50] [abbrv] git commit: bug CS-15278: Added global setting login.attempts.allowed which defines the maximum incorrect password attempts allowed. Also after the maximum attempts are reached the user account is disabled

bug CS-15278: Added global setting login.attempts.allowed which defines the maximum incorrect password attempts allowed.
Also after the maximum attempts are reached the user account is disabled


Project: http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/commit/a56631bc
Tree: http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/tree/a56631bc
Diff: http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/diff/a56631bc

Branch: refs/heads/javelin
Commit: a56631bc66713faaa99759eb374e11afd6f533d3
Parents: 41f6127
Author: Saksham Srivastava <sa...@citrix.com>
Authored: Wed Sep 12 19:16:16 2012 +0530
Committer: Nitin Mehta <ni...@citrix.com>
Committed: Wed Sep 12 19:35:24 2012 +0530

----------------------------------------------------------------------
 core/src/com/cloud/user/UserAccountVO.java         |   13 +++-
 server/src/com/cloud/configuration/Config.java     |    2 +-
 .../configuration/ConfigurationManagerImpl.java    |    1 +
 server/src/com/cloud/user/AccountManagerImpl.java  |   62 ++++++++++++++-
 setup/db/create-schema.sql                         |    1 +
 setup/db/db/schema-302to40.sql                     |    3 +
 6 files changed, 78 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/a56631bc/core/src/com/cloud/user/UserAccountVO.java
----------------------------------------------------------------------
diff --git a/core/src/com/cloud/user/UserAccountVO.java b/core/src/com/cloud/user/UserAccountVO.java
index 5e7c018..1236061 100644
--- a/core/src/com/cloud/user/UserAccountVO.java
+++ b/core/src/com/cloud/user/UserAccountVO.java
@@ -83,6 +83,9 @@ public class UserAccountVO implements UserAccount {
     @Column(name="is_registered")
     boolean registered;
 
+    @Column (name="incorrect_login_attempts")
+    int loginAttempts;
+
     @Column(name="account_name", table="account", insertable=false, updatable=false)
     private String accountName = null;
 
@@ -269,4 +272,12 @@ public class UserAccountVO implements UserAccount {
     public void setRegistered(boolean registered) {
         this.registered = registered;
     }
-}
\ No newline at end of file
+
+    public void setLoginAttempts(int loginAttempts) {
+        this.loginAttempts = loginAttempts;
+    }
+
+    public int getLoginAttempts() {
+        return loginAttempts;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/a56631bc/server/src/com/cloud/configuration/Config.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/configuration/Config.java b/server/src/com/cloud/configuration/Config.java
index 8554836..764e5ee 100755
--- a/server/src/com/cloud/configuration/Config.java
+++ b/server/src/com/cloud/configuration/Config.java
@@ -229,7 +229,7 @@ public enum Config {
     EnableEC2API("Advanced", ManagementServer.class, Boolean.class, "enable.ec2.api", "false", "enable EC2 API on CloudStack", null),
     EnableS3API("Advanced", ManagementServer.class, Boolean.class, "enable.s3.api", "false", "enable Amazon S3 API on CloudStack", null),
     RecreateSystemVmEnabled("Advanced", ManagementServer.class, Boolean.class, "recreate.systemvm.enabled", "false", "If true, will recreate system vm root disk whenever starting system vm", "true,false"),
-    
+    IncorrectLoginAttemptsAllowed("Advanced", ManagementServer.class, Integer.class, "incorrect.login.attempts.allowed", "5", "Incorrect login attempts allowed before the user is disabled", null),
     // Ovm
     OvmPublicNetwork("Hidden", ManagementServer.class, String.class, "ovm.public.network.device", null, "Specify the public bridge on host for public network", null),
     OvmPrivateNetwork("Hidden", ManagementServer.class, String.class, "ovm.private.network.device", null, "Specify the private bridge on host for private network", null),

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/a56631bc/server/src/com/cloud/configuration/ConfigurationManagerImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/configuration/ConfigurationManagerImpl.java b/server/src/com/cloud/configuration/ConfigurationManagerImpl.java
index f8deb15..ef940e8 100755
--- a/server/src/com/cloud/configuration/ConfigurationManagerImpl.java
+++ b/server/src/com/cloud/configuration/ConfigurationManagerImpl.java
@@ -274,6 +274,7 @@ public class ConfigurationManagerImpl implements ConfigurationManager, Configura
         configValuesForValidation.add("storage.cleanup.interval");
         configValuesForValidation.add("wait");
         configValuesForValidation.add("xen.heartbeat.interval");
+        configValuesForValidation.add("incorrect.login.attempts.allowed");
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/a56631bc/server/src/com/cloud/user/AccountManagerImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/user/AccountManagerImpl.java b/server/src/com/cloud/user/AccountManagerImpl.java
index 38153f3..fa9fafb 100755
--- a/server/src/com/cloud/user/AccountManagerImpl.java
+++ b/server/src/com/cloud/user/AccountManagerImpl.java
@@ -224,6 +224,8 @@ public class AccountManagerImpl implements AccountManager, AccountService, Manag
 
     private final ScheduledExecutorService _executor = Executors.newScheduledThreadPool(1, new NamedThreadFactory("AccountChecker"));
 
+    int _allowedLoginAttempts;
+
     UserVO _systemUser;
     AccountVO _systemAccount;
     @Inject(adapter = SecurityChecker.class)
@@ -248,6 +250,9 @@ public class AccountManagerImpl implements AccountManager, AccountService, Manag
         ConfigurationDao configDao = locator.getDao(ConfigurationDao.class);
         Map<String, String> configs = configDao.getConfiguration(params);
 
+        String loginAttempts = configs.get(Config.IncorrectLoginAttemptsAllowed.key());
+        _allowedLoginAttempts = NumbersUtil.parseInt(loginAttempts, 5);
+
         String value = configs.get(Config.AccountCleanupInterval.key());
         _cleanupInterval = NumbersUtil.parseInt(value, 60 * 60 * 24); // 1 day.
 
@@ -302,6 +307,13 @@ public class AccountManagerImpl implements AccountManager, AccountService, Manag
         return (accountType == Account.ACCOUNT_TYPE_RESOURCE_DOMAIN_ADMIN);
     }
 
+    public boolean isInternalAccount(short accountType) {
+        if (isRootAdmin(accountType) || (accountType == Account.ACCOUNT_ID_SYSTEM)) {
+            return true;
+        }
+        return false;
+    }
+
     @Override
     public void checkAccess(Account caller, Domain domain) throws PermissionDeniedException {
         for (SecurityChecker checker : _securityCheckers) {
@@ -420,6 +432,25 @@ public class AccountManagerImpl implements AccountManager, AccountService, Manag
 
     }
 
+    @DB
+    public void updateLoginAttempts(Long id, int attempts, boolean toDisable) {
+        Transaction txn = Transaction.currentTxn();
+        txn.start();
+        try {
+            UserAccountVO user = null;
+            user = _userAccountDao.lockRow(id, true);
+            user.setLoginAttempts(attempts);
+            if(toDisable) {
+                user.setState(State.disabled.toString());
+            }
+            _userAccountDao.update(id, user);
+             txn.commit();
+        } catch (Exception e) {
+            s_logger.error("Failed to update login attempts for user with id " + id );
+        }
+        txn.close();
+    }
+
     private boolean doSetUserStatus(long userId, State state) {
         UserVO userForUpdate = _userDao.createForUpdate();
         userForUpdate.setState(state);
@@ -732,7 +763,7 @@ public class AccountManagerImpl implements AccountManager, AccountService, Manag
         if (domainId == null) {
             domainId = DomainVO.ROOT_DOMAIN;
         }
-        
+
         if (userName.isEmpty()) {
             throw new InvalidParameterValueException("Username is empty");
         }
@@ -740,7 +771,7 @@ public class AccountManagerImpl implements AccountManager, AccountService, Manag
         if (firstName.isEmpty()) {
             throw new InvalidParameterValueException("Firstname is empty");
         }
-        
+
         if (lastName.isEmpty()) {
             throw new InvalidParameterValueException("Lastname is empty");
         }
@@ -1002,6 +1033,8 @@ public class AccountManagerImpl implements AccountManager, AccountService, Manag
         txn.commit();
 
         if (success) {
+            // whenever the user is successfully enabled, reset the login attempts to zero
+            updateLoginAttempts(userId, 0, false);
             return _userAccountDao.findById(userId);
         } else {
             throw new CloudRuntimeException("Unable to enable user " + userId);
@@ -1818,11 +1851,36 @@ public class AccountManagerImpl implements AccountManager, AccountService, Manag
                 throw new CloudAuthenticationException("User " + username + " in domain " + domainName + " is disabled/locked (or account is disabled/locked)");
                 // return null;
             }
+            // Whenever the user is able to log in successfully, reset the login attempts to zero
+            if(!isInternalAccount(userAccount.getType()))
+                updateLoginAttempts(userAccount.getId(), 0, false);
+
             return userAccount;
         } else {
             if (s_logger.isDebugEnabled()) {
                 s_logger.debug("Unable to authenticate user with username " + username + " in domain " + domainId);
             }
+
+            UserAccount userAccount = _userAccountDao.getUserAccount(username, domainId);
+            UserAccountVO user = _userAccountDao.findById(userAccount.getId());
+            if (user != null) {
+                if ((user.getState().toString()).equals("enabled")) {
+                    if (!isInternalAccount(user.getType())) {
+                        //Internal accounts are not disabled
+                        int attemptsMade = user.getLoginAttempts() + 1;
+                        if (attemptsMade < _allowedLoginAttempts) {
+                            updateLoginAttempts(userAccount.getId(), attemptsMade, false);
+                            s_logger.warn("Login attempt failed. You have " + ( _allowedLoginAttempts - attemptsMade ) + " attempt(s) remaining");
+                        } else {
+                            updateLoginAttempts(userAccount.getId(), _allowedLoginAttempts, true);
+                            s_logger.warn("User " + user.getUsername() + " has been disabled due to multiple failed login attempts." +
+                                    " Please contact admin.");
+                        }
+                    }
+                } else {
+                    s_logger.info("User " + user.getUsername() + " is disabled/locked");
+                }
+            }
             return null;
         }
     }

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/a56631bc/setup/db/create-schema.sql
----------------------------------------------------------------------
diff --git a/setup/db/create-schema.sql b/setup/db/create-schema.sql
index bb6dc5d..5b6dc04 100755
--- a/setup/db/create-schema.sql
+++ b/setup/db/create-schema.sql
@@ -890,6 +890,7 @@ CREATE TABLE  `cloud`.`user` (
   `timezone` varchar(30) default NULL,
   `registration_token` varchar(255) default NULL,
   `is_registered` tinyint NOT NULL DEFAULT 0 COMMENT '1: yes, 0: no',
+  `incorrect_login_attempts` integer unsigned NOT NULL DEFAULT 0,
   PRIMARY KEY  (`id`),
   INDEX `i_user__removed`(`removed`),
   INDEX `i_user__secret_key_removed`(`secret_key`, `removed`),

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/a56631bc/setup/db/db/schema-302to40.sql
----------------------------------------------------------------------
diff --git a/setup/db/db/schema-302to40.sql b/setup/db/db/schema-302to40.sql
index d70697b..0916156 100644
--- a/setup/db/db/schema-302to40.sql
+++ b/setup/db/db/schema-302to40.sql
@@ -472,3 +472,6 @@ INSERT IGNORE INTO `cloud`.`configuration` VALUES ('Network', 'DEFAULT', 'manage
 INSERT IGNORE INTO `cloud`.`configuration` VALUES ('Network', 'DEFAULT', 'management-server', 'site2site.vpn.customergateway.subnets.limit', '10', 'The maximum number of subnets per customer gateway');
 
 INSERT IGNORE INTO `cloud`.`guest_os_category` VALUES ('11','None',NULL); 
+ALTER TABLE `cloud`.`user` ADD COLUMN `incorrect_login_attempts` integer unsigned NOT NULL DEFAULT '0';
+INSERT IGNORE INTO `cloud`.`configuration` VALUES ('Advanced', 'DEFAULT', 'management-server', 'incorrect.login.attempts.allowed', '5', 'Incorrect login attempts allowed before the user is disabled');
+