/**
 * Copyright © 2017 IBM Corporation
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include <cstring>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <shadow.h>
#include <array>
#include <random>
#include <errno.h>
#include <xyz/openbmc_project/Common/error.hpp>
#include <phosphor-logging/log.hpp>
#include <phosphor-logging/elog.hpp>
#include <phosphor-logging/elog-errors.hpp>
#include "user.hpp"
#include "file.hpp"
#include "shadowlock.hpp"
#include "config.h"
namespace phosphor
{
namespace user
{

constexpr auto SHADOW_FILE = "/etc/shadow";

// See crypt(3)
constexpr int SALT_LENGTH = 16;

using namespace phosphor::logging;
using InsufficientPermission = sdbusplus::xyz::openbmc_project::Common::
                                    Error::InsufficientPermission;
using InternalFailure = sdbusplus::xyz::openbmc_project::Common::
                                    Error::InternalFailure;
// Sets or updates the password
void User::setPassword(std::string newPassword)
{
    // Gate any access to /etc/shadow
    phosphor::user::shadow::Lock lock();

    // rewind to the start of shadow entry
    setspent();

    // Generate a random string from set [A-Za-z0-9./]
    std::string salt{};
    salt.resize(SALT_LENGTH);
    salt = randomString(SALT_LENGTH);

    // Apply the change. Updates could be directly made to shadow
    // but then any update must be contained within the boundary
    // of that user, else it would run into next entry and thus
    // corrupting it. Classic example is when a password is set on
    // a user ID that does not have a prior password
    applyPassword(SHADOW_FILE, newPassword, salt);
    return;
}

void User::applyPassword(const std::string& shadowFile,
                         const std::string& password,
                         const std::string& salt)
{
    // Needed by getspnam_r
    struct spwd shdp;
    struct spwd* pshdp;

    // This should be fine even if SHA512 is used.
    std::array<char,1024> buffer{};

    // Open the shadow file for reading
    phosphor::user::File shadow(shadowFile, "r");
    if ((shadow)() == NULL)
    {
        return raiseException(errno, "Error opening shadow file");
    }

    // open temp shadow file, by suffixing random name in shadow file name.
    std::vector<char> tempFileName(shadowFile.begin(), shadowFile.end());
    std::vector<char> fileTemplate = {
                             '_', '_', 'X', 'X', 'X', 'X', 'X', 'X', '\0' };
    tempFileName.insert(
              tempFileName.end(), fileTemplate.begin(), fileTemplate.end());

    int fd = mkstemp(tempFileName.data());
    if (fd == -1)
    {
        return raiseException(errno, "Error creating temp shadow file");
    }

    std::string strTempFileName(tempFileName.data());
    // Open the temp shadow file for writing from provided fd
    // By "true", remove it at exit if still there.
    // This is needed to cleanup the temp file at exception
    phosphor::user::File temp(fd, strTempFileName, "w", true);
    if ((temp)() == NULL)
    {
        close(fd);
        return raiseException(errno, "Error opening temp shadow file");
    }
    fd = -1; // don't use fd anymore, as the File object owns it

    // Change the permission of this new temp file
    // to be same as shadow so that it's secure
    struct stat st{};
    auto r = fstat(fileno((shadow)()), &st);
    if (r < 0)
    {
        return raiseException(errno, "Error reading shadow file mode");
    }

    r = fchmod(fileno((temp)()), st.st_mode);
    if (r < 0)
    {
        return raiseException(errno, "Error setting temp file mode");
    }

    // Read shadow file and process
    while (true)
    {
        auto r = fgetspent_r((shadow)(), &shdp, buffer.data(),
                             buffer.max_size(), &pshdp);
        if (r)
        {
            if (errno == EACCES || errno == ERANGE)
            {
                return raiseException(errno, "Error reading shadow file");
            }
            else
            {
                // Seem to have run over all
                break;
            }
        }

        // Hash of password if the user matches
        std::string hash{};

        // Matched user
        if (user == shdp.sp_namp)
        {
            // Update with new hashed password
            hash = hashPassword(shdp.sp_pwdp, password, salt);
            shdp.sp_pwdp = const_cast<char*>(hash.c_str());
        }

        // Apply
        r = putspent(&shdp, (temp)());
        if (r < 0)
        {
            return raiseException(errno, "Error updating temp shadow file");
        }
    } // All entries

    // Done
    endspent();
    // flush contents to file first, before renaming to avoid
    // corruption during power failure
    fflush((temp)());

    // Everything must be fine at this point
    fs::rename(strTempFileName, shadowFile);
    return;
}

void User::raiseException(int errNo, const std::string& errMsg)
{
    using namespace std::string_literals;
    if (errNo == EACCES)
    {
        auto message = "Access denied "s + errMsg;
        log<level::ERR>(message.c_str());
        elog<InsufficientPermission>();
    }
    else
    {
        log<level::ERR>(errMsg.c_str(),
                entry("USER=%s",user.c_str()),
                    entry("ERRNO=%d", errNo));
        elog<InternalFailure>();
    }
}

std::string User::hashPassword(char* spPwdp,
                               const std::string& password,
                               const std::string& salt)
{
    // Parse and get crypt algo
    auto cryptAlgo = getCryptField(spPwdp);
    if (cryptAlgo.empty())
    {
        log<level::ERR>("Error finding crypt algo",
                entry("USER=%s",user.c_str()));
        elog<InternalFailure>();
    }

    // Update shadow password pointer with hash
    auto saltString = getSaltString(cryptAlgo, salt);
    return generateHash(password, saltString);
}

// Returns a random string in set [A-Za-z0-9./]
// of size numChars
const std::string User::randomString(int length)
{
    // Populated random string
    std::string random{};

    // Needed per crypt(3)
    std::string set = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijk"
                      "lmnopqrstuvwxyz0123456789./";

    // Will be used to obtain a seed for the random number engine
    std::random_device rd;

    // Standard mersenne_twister_engine seeded with rd()
    std::mt19937 gen(rd());

    std::uniform_int_distribution<> dis(0, set.size()-1);
    for (int count = 0; count < length; count++)
    {
        // Use dis to transform the random unsigned int generated by
        // gen into a int in [1, SALT_LENGTH]
        random.push_back(set.at(dis(gen)));
    }
    return random;
}

// Extract crypto algorithm field
CryptAlgo User::getCryptField(char* spPwdp)
{
    char* savePtr{};
    if (std::string{spPwdp}.front() != '$')
    {
        return DEFAULT_CRYPT_ALGO;
    }
    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
