Extract crypto algorithm field and add utility functions

Password field of a user in /etc/shadow contains 3 parts:
[Crypt algorithm, Salt, encrypted password]

Example: A value of "1" in crypt algorithm maps to MD5

Need to use the same crypt algorithm that is already used
before when the new password is to be updated.

Change-Id: Ib7d8e0ad6f3bcce30f5c2be89b4e033230c07bf4
Signed-off-by: Vishwanatha Subbanna <vishwa@linux.vnet.ibm.com>
diff --git a/user.cpp b/user.cpp
index 0a6727b..f4b0e5e 100644
--- a/user.cpp
+++ b/user.cpp
@@ -13,16 +13,70 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+#include <cstring>
+#include <unistd.h>
+#include <sys/types.h>
+#include <shadow.h>
+#include <array>
 #include "user.hpp"
 namespace phosphor
 {
 namespace user
 {
 
+// Sets or updates the password
 void User::setPassword(std::string newPassword)
 {
+    // Needed by getspnam_r
+    struct spwd shdp;
+    struct spwd* pshdp;
+
+    // This should be fine even if SHA512 is used.
+    std::array<char,1024> buffer{};
+
+    // 1: Read /etc/shadow for the user
+    auto r = getspnam_r(user.c_str(), &shdp, buffer.data(),
+                        buffer.max_size(), &pshdp);
+    if (r < 0)
+    {
+        return;
+        // TODO: Throw an error
+    }
+
+    // Done reading
+    endspent();
+
+    // 2: Parse and get crypt algo
+    auto cryptAlgo = getCryptField(shdp.sp_pwdp);
+    if (cryptAlgo.empty())
+    {
+        // TODO: Throw error getting crypt field
+    }
+
+    // TODO: Update the password in next commit
     return;
 }
 
+// Extract crypto algorithm field
+CryptAlgo User::getCryptField(char* spPwdp)
+{
+    char* savePtr{};
+    return strtok_r(spPwdp, "$", &savePtr);
+}
+
+// Returns specific format of salt string
+std::string User::getSaltString(const std::string& crypt,
+                                const std::string& salt)
+{
+    return '$' + crypt + '$' + salt + '$';
+}
+
+// Given a password and salt, generates hash
+std::string User::generateHash(const std::string& password,
+                               const std::string& salt)
+{
+    return crypt(password.c_str(), salt.c_str());
+}
+
 } // namespace user
 } // namespace phosphor