Add support for MAX PASSWORD LENGTH

As per NIST Guideline  https://pages.nist.gov/800-63-4/sp800-63b.html

Verifiers and CSPs SHOULD permit a MaxPasswordLength must be at least
64 characters therefore added this support. Added this as a meson option
each organization can configure their own MAX PASSWORD LENGTH. Default
value is as per NIST guideline recommendation

Testing:

Validated MinPasswordLangth > MaxPasswordLength test cases and worked
as expected.

Change-Id: I75b0056a0acc038d3103016ebbdaa6be08df74a1
Signed-off-by: Chandramohan Harkude <chandramohan.harkude@gmail.com>
diff --git a/meson.build b/meson.build
index 6bbea64..c22c4c4 100644
--- a/meson.build
+++ b/meson.build
@@ -71,6 +71,12 @@
     description: 'path of directory having persisted LDAP configuration enabled property.',
 )
 
+conf_data.set(
+    'MAX_PASSWORD_LENGTH',
+    get_option('MAX_PASSWORD_LENGTH'),
+    description: 'Maximum password length',
+)
+
 conf_header = configure_file(output: 'config.h', configuration: conf_data)
 
 phosphor_dbus_interfaces_dep = dependency('phosphor-dbus-interfaces')
diff --git a/meson.options b/meson.options
index ace1bdd..44551ad 100644
--- a/meson.options
+++ b/meson.options
@@ -5,3 +5,10 @@
     description: 'Enable management of the root user',
     value: 'enabled',
 )
+
+option(
+    'MAX_PASSWORD_LENGTH',
+    type: 'integer',
+    value: 64,
+    description: 'Max password Length default value as per NIST guideline recommendation',
+)
diff --git a/test/user_mgr_test.cpp b/test/user_mgr_test.cpp
index 9dd799a..187d3c2 100644
--- a/test/user_mgr_test.cpp
+++ b/test/user_mgr_test.cpp
@@ -802,6 +802,17 @@
     EXPECT_EQ(AccountPolicyIface::minPasswordLength(), 8);
 }
 
+TEST_F(UserMgrInTest, MinPasswordLengthGreaterThanMaxPasswordLength)
+{
+    initializeAccountPolicy();
+
+    EXPECT_EQ(AccountPolicyIface::minPasswordLength(), 8);
+    EXPECT_THROW(
+        UserMgr::minPasswordLength(maxPasswdLength + 1),
+        sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
+    EXPECT_EQ(AccountPolicyIface::minPasswordLength(), 8);
+}
+
 TEST_F(UserMgrInTest, RememberOldPasswordTimesReturnsIfValueIsTheSame)
 {
     initializeAccountPolicy();
diff --git a/user_mgr.cpp b/user_mgr.cpp
index f4e745f..2aa15e8 100644
--- a/user_mgr.cpp
+++ b/user_mgr.cpp
@@ -60,6 +60,7 @@
 static constexpr int success = 0;
 static constexpr int failure = -1;
 
+uint8_t maxPasswdLength = MAX_PASSWORD_LENGTH;
 // pam modules related
 static constexpr const char* minPasswdLenProp = "minlen";
 static constexpr const char* remOldPasswdCount = "remember";
@@ -589,14 +590,15 @@
     {
         return value;
     }
-    if (value < minPasswdLength)
+    if (value < minPasswdLength || value > maxPasswdLength)
     {
+        std::string valueStr = std::to_string(value);
         lg2::error("Attempting to set minPasswordLength to {VALUE}, less than "
-                   "{MINVALUE}",
-                   "VALUE", value, "MINVALUE", minPasswdLength);
-        elog<InvalidArgument>(
-            Argument::ARGUMENT_NAME("minPasswordLength"),
-            Argument::ARGUMENT_VALUE(std::to_string(value).c_str()));
+                   "{MINPASSWORDLENGTH} or greater than {MAXPASSWORDLENGTH}",
+                   "VALUE", value, "MINPASSWORDLENGTH", minPasswdLength,
+                   "MAXPASSWORDLENGTH", maxPasswdLength);
+        elog<InvalidArgument>(Argument::ARGUMENT_NAME("minPasswordLength"),
+                              Argument::ARGUMENT_VALUE(valueStr.data()));
     }
     if (setPamModuleConfValue(pwQualityConfigFile, minPasswdLenProp,
                               std::to_string(value)) != success)
diff --git a/user_mgr.hpp b/user_mgr.hpp
index b69cb87..13f3c8e 100644
--- a/user_mgr.hpp
+++ b/user_mgr.hpp
@@ -44,6 +44,7 @@
 inline constexpr size_t ipmiMaxUsers = 15;
 inline constexpr size_t maxSystemUsers = 30;
 inline constexpr uint8_t minPasswdLength = 8;
+extern uint8_t maxPasswdLength; // MAX_PASSWORD_LENGTH;
 inline constexpr size_t maxSystemGroupNameLength = 32;
 inline constexpr size_t maxSystemGroupCount = 64;