Added passsword policy parameters
Following parameters are added as compile time option to
control the complexitiy of the password.
- Minimum upper case characters
- Minimum lower case characters
- Minimum digits
NOTE: Add of all should be less than or equal to
minimum password length.
Tested:
1) Sum of all was greater then min password length
2) Negative value test.
3) Password strictness was getting imposed as the given configuration
Signed-off-by: Ratan Gupta <ratankgupta31@gmail.com>
diff --git a/configure.ac b/configure.ac
index c30e109..d36b4f1 100644
--- a/configure.ac
+++ b/configure.ac
@@ -40,6 +40,18 @@
AS_IF([test "x$DEFAULT_CRYPT_ALGO" == "x"], [DEFAULT_CRYPT_ALGO="1"])
AC_DEFINE_UNQUOTED([DEFAULT_CRYPT_ALGO], ["$DEFAULT_CRYPT_ALGO"], [The default crypt algorithm if one not found in shadow])
+AC_ARG_VAR(MIN_UCASE_CHRS, [minimum number of upper case characters in the password])
+AS_IF([test "x$MIN_UCASE_CHRS" == "x"], [MIN_UCASE_CHRS=0])
+AC_DEFINE_UNQUOTED([MIN_UCASE_CHRS], [$MIN_UCASE_CHRS], [minimum number of upper case characters in the password])
+
+AC_ARG_VAR(MIN_LCASE_CHRS, [minimum number of lower case characters in the password])
+AS_IF([test "x$MIN_LCASE_CHRS" == "x"], [MIN_LCASE_CHRS=0])
+AC_DEFINE_UNQUOTED([MIN_LCASE_CHRS], [$MIN_LCASE_CHRS], [minimum number of lower case characters in the password])
+
+AC_ARG_VAR(MIN_DIGITS, [minimum number of digits in the password])
+AS_IF([test "x$MIN_DIGITS" == "x"], [MIN_DIGITS=0])
+AC_DEFINE_UNQUOTED([MIN_DIGITS], [$MIN_DIGITS], [minimum number of digits in the password])
+
# Check/set gtest specific functions.
AX_PTHREAD([GTEST_CPPFLAGS="-DGTEST_HAS_PTHREAD=1"],[GTEST_CPPFLAGS="-DGTEST_HAS_PTHREAD=0"])
AC_SUBST(GTEST_CPPFLAGS)
diff --git a/user_mgr.cpp b/user_mgr.cpp
index 05aa6e7..2fd423e 100644
--- a/user_mgr.cpp
+++ b/user_mgr.cpp
@@ -69,6 +69,9 @@
static constexpr const char* unlockTimeout = "unlock_time";
static constexpr const char* pamPasswdConfigFile = "/etc/pam.d/common-password";
static constexpr const char* pamAuthConfigFile = "/etc/pam.d/common-auth";
+static constexpr const char* minLcaseCharsProp = "lcredit";
+static constexpr const char* minUcaseCharsProp = "ucredit";
+static constexpr const char* minDigitProp = "dcredit";
// Object Manager related
static constexpr const char* ldapMgrObjBasePath =
@@ -1172,7 +1175,8 @@
std::sort(groupsMgr.begin(), groupsMgr.end());
UserMgrIface::allGroups(groupsMgr);
std::string valueStr;
- auto value = minPasswdLength;
+ auto pwdLength = minPasswdLength;
+ auto value = 0;
unsigned long tmp = 0;
if (getPamModuleArgValue(pamCrackLib, minPasswdLenProp, valueStr) !=
success)
@@ -1188,7 +1192,7 @@
{
throw std::out_of_range("Out of range");
}
- value = static_cast<decltype(value)>(tmp);
+ pwdLength = static_cast<decltype(pwdLength)>(tmp);
}
catch (const std::exception& e)
{
@@ -1196,7 +1200,7 @@
entry("WHAT=%s", e.what()));
throw;
}
- AccountPolicyIface::minPasswordLength(value);
+ AccountPolicyIface::minPasswordLength(pwdLength);
}
valueStr.clear();
if (getPamModuleArgValue(pamPWHistory, remOldPasswdCount, valueStr) !=
@@ -1274,6 +1278,46 @@
}
AccountPolicyIface::accountUnlockTimeout(value32);
}
+
+ // Don't consume all the configuratios if the sum of all other
+ // chars is greater then the min password length.
+ if (pwdLength > (MIN_LCASE_CHRS + MIN_UCASE_CHRS + MIN_DIGITS))
+ {
+ int val =
+ (MIN_LCASE_CHRS * (-1)); // value shoukd be in negative to tell the
+ // minimum number of digits required
+ if (val > 0 || MIN_LCASE_CHRS > std::numeric_limits<uint8_t>::max() ||
+ setPamModuleArgValue(pamCrackLib, minLcaseCharsProp,
+ std::to_string(val)) != success)
+ {
+ log<level::ERR>("Unable to set minLowercase characters",
+ entry("MIN_LCASE_CHRS=%d", MIN_LCASE_CHRS));
+ }
+ val = (MIN_UCASE_CHRS * (-1));
+
+ if (val > 0 || MIN_UCASE_CHRS > std::numeric_limits<uint8_t>::max() ||
+ setPamModuleArgValue(pamCrackLib, minUcaseCharsProp,
+ std::to_string(val)) != success)
+ {
+ log<level::ERR>("Unable to set minUppercase characters",
+ entry("MIN_UCASE_CHRS=%d", MIN_UCASE_CHRS));
+ }
+ val = (MIN_DIGITS * (-1));
+ if (val > 0 || MIN_DIGITS > std::numeric_limits<uint8_t>::max() ||
+ setPamModuleArgValue(pamCrackLib, minDigitProp,
+ std::to_string(val)) != success)
+ {
+ log<level::ERR>("Unable to set mindigit",
+ entry("MIN_DIGITS=%d", MIN_DIGITS));
+ }
+ }
+ else
+ {
+
+ log<level::ERR>("Min password length should be >= sum of "
+ "lowercase, uppercase, digits");
+ }
+
initUserObjects();
// emit the signal