#include "ldap_config.hpp"

#include "ldap_config_mgr.hpp"
#include "ldap_mapper_serialize.hpp"
#include "utils.hpp"

#include <cereal/archives/binary.hpp>
#include <cereal/types/string.hpp>
#include <cereal/types/vector.hpp>
#include <xyz/openbmc_project/Common/error.hpp>
#include <xyz/openbmc_project/User/Common/error.hpp>

#include <filesystem>
#include <fstream>
#include <sstream>

// Register class version
// From cereal documentation;
// "This macro should be placed at global scope"
CEREAL_CLASS_VERSION(phosphor::ldap::Config, CLASS_VERSION);

namespace phosphor
{
namespace ldap
{

constexpr auto nslcdService = "nslcd.service";
constexpr auto nscdService = "nscd.service";
constexpr auto LDAPscheme = "ldap";
constexpr auto LDAPSscheme = "ldaps";
constexpr auto certObjPath = "/xyz/openbmc_project/certs/client/ldap/1";
constexpr auto certRootPath = "/xyz/openbmc_project/certs/client/ldap";
constexpr auto authObjPath = "/xyz/openbmc_project/certs/authority/ldap";
constexpr auto certIface = "xyz.openbmc_project.Certs.Certificate";
constexpr auto certProperty = "CertificateString";

using namespace phosphor::logging;
using namespace sdbusplus::xyz::openbmc_project::Common::Error;
namespace fs = std::filesystem;

using Argument = xyz::openbmc_project::Common::InvalidArgument;
using NotAllowed = sdbusplus::xyz::openbmc_project::Common::Error::NotAllowed;
using NotAllowedArgument = xyz::openbmc_project::Common::NotAllowed;
using PrivilegeMappingExists = sdbusplus::xyz::openbmc_project::User::Common::
    Error::PrivilegeMappingExists;

using Line = std::string;
using Key = std::string;
using Val = std::string;
using ConfigInfo = std::map<Key, Val>;

Config::Config(sdbusplus::bus::bus& bus, const char* path, const char* filePath,
               const char* caCertFile, const char* certFile, bool secureLDAP,
               std::string ldapServerURI, std::string ldapBindDN,
               std::string ldapBaseDN, std::string&& ldapBindDNPassword,
               ConfigIface::SearchScope ldapSearchScope,
               ConfigIface::Type ldapType, bool ldapServiceEnabled,
               std::string userNameAttr, std::string groupNameAttr,
               ConfigMgr& parent) :
    Ifaces(bus, path, Ifaces::action::defer_emit),
    secureLDAP(secureLDAP), ldapBindPassword(std::move(ldapBindDNPassword)),
    tlsCacertFile(caCertFile), tlsCertFile(certFile), configFilePath(filePath),
    objectPath(path), bus(bus), parent(parent),
    certificateInstalledSignal(
        bus, sdbusplus::bus::match::rules::interfacesAdded(certRootPath),
        std::bind(std::mem_fn(&Config::certificateInstalled), this,
                  std::placeholders::_1)),

    cacertificateInstalledSignal(
        bus, sdbusplus::bus::match::rules::interfacesAdded(authObjPath),
        std::bind(std::mem_fn(&Config::certificateInstalled), this,
                  std::placeholders::_1)),

    certificateChangedSignal(
        bus,
        sdbusplus::bus::match::rules::propertiesChanged(certObjPath, certIface),
        std::bind(std::mem_fn(&Config::certificateChanged), this,
                  std::placeholders::_1))
{
    ConfigIface::ldapServerURI(ldapServerURI);
    ConfigIface::ldapBindDN(ldapBindDN);
    ConfigIface::ldapBaseDN(ldapBaseDN);
    ConfigIface::ldapSearchScope(ldapSearchScope);
    ConfigIface::ldapType(ldapType);
    EnableIface::enabled(ldapServiceEnabled);
    ConfigIface::userNameAttribute(userNameAttr);
    ConfigIface::groupNameAttribute(groupNameAttr);
    // NOTE: Don't update the bindDN password under ConfigIface
    if (enabled())
    {
        writeConfig();
    }
    // save the config.
    configPersistPath = parent.dbusPersistentPath;
    configPersistPath += objectPath;

    // create the persistent directory
    fs::create_directories(configPersistPath);

    configPersistPath += "/config";

    serialize();

    // Emit deferred signal.
    this->emit_object_added();
    parent.startOrStopService(nslcdService, enabled());
}

Config::Config(sdbusplus::bus::bus& bus, const char* path, const char* filePath,
               const char* caCertFile, const char* certFile,
               ConfigIface::Type ldapType, ConfigMgr& parent) :
    Ifaces(bus, path, Ifaces::action::defer_emit),
    secureLDAP(false), tlsCacertFile(caCertFile), tlsCertFile(certFile),
    configFilePath(filePath), objectPath(path), bus(bus), parent(parent),
    certificateInstalledSignal(
        bus, sdbusplus::bus::match::rules::interfacesAdded(certRootPath),
        std::bind(std::mem_fn(&Config::certificateInstalled), this,
                  std::placeholders::_1)),
    cacertificateInstalledSignal(
        bus, sdbusplus::bus::match::rules::interfacesAdded(authObjPath),
        std::bind(std::mem_fn(&Config::certificateInstalled), this,
                  std::placeholders::_1)),
    certificateChangedSignal(
        bus,
        sdbusplus::bus::match::rules::propertiesChanged(certObjPath, certIface),
        std::bind(std::mem_fn(&Config::certificateChanged), this,
                  std::placeholders::_1))
{
    ConfigIface::ldapType(ldapType);

    configPersistPath = parent.dbusPersistentPath;
    configPersistPath += objectPath;

    // create the persistent directory
    fs::create_directories(configPersistPath);

    configPersistPath += "/config";
}

void Config::certificateInstalled(sdbusplus::message::message& /*msg*/)
{
    try
    {
        if (enabled())
        {
            writeConfig();
        }
        parent.startOrStopService(nslcdService, enabled());
    }
    catch (const InternalFailure& e)
    {
        throw;
    }
    catch (const std::exception& e)
    {
        log<level::ERR>(e.what());
        elog<InternalFailure>();
    }
}

void Config::certificateChanged(sdbusplus::message::message& msg)
{
    std::string objectName;
    std::map<std::string, std::variant<std::string>> msgData;
    msg.read(objectName, msgData);
    auto valPropMap = msgData.find(certProperty);
    {
        if (valPropMap != msgData.end())
        {
            try
            {
                if (enabled())
                {

                    writeConfig();
                }
                parent.startOrStopService(nslcdService, enabled());
            }
            catch (const InternalFailure& e)
            {
                throw;
            }
            catch (const std::exception& e)
            {
                log<level::ERR>(e.what());
                elog<InternalFailure>();
            }
        }
    }
}

void Config::writeConfig()
{
    std::stringstream confData;
    auto isPwdTobeWritten = false;
    std::string userNameAttr;

    confData << "uid root\n";
    confData << "gid root\n\n";
    confData << "ldap_version 3\n\n";
    confData << "timelimit 30\n";
    confData << "bind_timelimit 30\n";
    confData << "pagesize 1000\n";
    confData << "referrals off\n\n";
    confData << "uri " << ldapServerURI() << "\n\n";
    confData << "base " << ldapBaseDN() << "\n\n";
    confData << "binddn " << ldapBindDN() << "\n";
    if (!ldapBindPassword.empty())
    {
        confData << "bindpw " << ldapBindPassword << "\n";
        isPwdTobeWritten = true;
    }
    confData << "\n";
    switch (ldapSearchScope())
    {
        case ConfigIface::SearchScope::sub:
            confData << "scope sub\n\n";
            break;
        case ConfigIface::SearchScope::one:
            confData << "scope one\n\n";
            break;
        case ConfigIface::SearchScope::base:
            confData << "scope base\n\n";
            break;
    }
    confData << "base passwd " << ldapBaseDN() << "\n";
    confData << "base shadow " << ldapBaseDN() << "\n\n";
    if (secureLDAP == true)
    {
        confData << "ssl on\n";
        confData << "tls_reqcert hard\n";
        if (fs::is_directory(tlsCacertFile.c_str()))
        {
            confData << "tls_cacertdir " << tlsCacertFile.c_str() << "\n";
        }
        else
        {
            confData << "tls_cacertfile " << tlsCacertFile.c_str() << "\n";
        }
        if (fs::exists(tlsCertFile.c_str()))
        {
            confData << "tls_cert " << tlsCertFile.c_str() << "\n";
            confData << "tls_key " << tlsCertFile.c_str() << "\n";
        }
    }
    else
    {
        confData << "ssl off\n";
    }
    confData << "\n";
    if (ldapType() == ConfigIface::Type::ActiveDirectory)
    {
        if (ConfigIface::userNameAttribute().empty())
        {
            ConfigIface::userNameAttribute("sAMAccountName");
        }
        if (ConfigIface::groupNameAttribute().empty())
        {
            ConfigIface::groupNameAttribute("primaryGroupID");
        }
        confData << "filter passwd (&(objectClass=user)(objectClass=person)"
                    "(!(objectClass=computer)))\n";
        confData
            << "filter group (|(objectclass=group)(objectclass=groupofnames) "
               "(objectclass=groupofuniquenames))\n";
        confData << "map passwd uid              "
                 << ConfigIface::userNameAttribute() << "\n";
        confData << "map passwd uidNumber        "
                    "objectSid:S-1-5-21-3623811015-3361044348-30300820\n";
        confData << "map passwd gidNumber        "
                 << ConfigIface::groupNameAttribute() << "\n";
        confData << "map passwd homeDirectory    \"/home/$sAMAccountName\"\n";
        confData << "map passwd gecos            displayName\n";
        confData << "map passwd loginShell       \"/bin/bash\"\n";
        confData << "map group gidNumber         "
                    "objectSid:S-1-5-21-3623811015-3361044348-30300820\n";
        confData << "map group cn                "
                 << ConfigIface::userNameAttribute() << "\n";
        confData << "nss_initgroups_ignoreusers ALLLOCAL\n";
    }
    else if (ldapType() == ConfigIface::Type::OpenLdap)
    {
        if (ConfigIface::userNameAttribute().empty())
        {
            ConfigIface::userNameAttribute("cn");
        }
        if (ConfigIface::groupNameAttribute().empty())
        {
            ConfigIface::groupNameAttribute("gidNumber");
        }
        confData << "filter passwd (objectclass=*)\n";
        confData << "map passwd gecos displayName\n";
        confData << "filter group (objectclass=posixGroup)\n";
        confData << "map passwd uid              "
                 << ConfigIface::userNameAttribute() << "\n";
        confData << "map passwd gidNumber        "
                 << ConfigIface::groupNameAttribute() << "\n";
        confData << "nss_initgroups_ignoreusers ALLLOCAL\n";
    }
    try
    {
        std::fstream stream(configFilePath.c_str(), std::fstream::out);
        // remove the read permission from others if password is being written.
        // nslcd forces this behaviour.
        auto permission = fs::perms::owner_read | fs::perms::owner_write |
                          fs::perms::group_read;
        if (isPwdTobeWritten)
        {
            fs::permissions(configFilePath, permission);
        }
        else
        {
            fs::permissions(configFilePath,
                            permission | fs::perms::others_read);
        }

        stream << confData.str();
        stream.flush();
        stream.close();
    }
    catch (const std::exception& e)
    {
        log<level::ERR>(e.what());
        elog<InternalFailure>();
    }
    return;
}

std::string Config::ldapBindDNPassword(std::string value)
{
    // Don't update the D-bus object, this is just to
    // facilitate if user wants to change the bind dn password
    // once d-bus object gets created.
    ldapBindPassword = value;
    try
    {
        if (enabled())
        {
            writeConfig();
            parent.startOrStopService(nslcdService, enabled());
        }
        serialize();
    }
    catch (const InternalFailure& e)
    {
        throw;
    }
    catch (const std::exception& e)
    {
        log<level::ERR>(e.what());
        elog<InternalFailure>();
    }
    return value;
}

std::string Config::ldapServerURI(std::string value)
{
    std::string val;
    try
    {
        if (value == ldapServerURI())
        {
            return value;
        }
        if (isValidLDAPURI(value, LDAPSscheme))
        {
            secureLDAP = true;
        }
        else if (isValidLDAPURI(value, LDAPscheme))
        {
            secureLDAP = false;
        }
        else
        {
            log<level::ERR>("bad LDAP Server URI",
                            entry("LDAPSERVERURI=%s", value.c_str()));
            elog<InvalidArgument>(Argument::ARGUMENT_NAME("ldapServerURI"),
                                  Argument::ARGUMENT_VALUE(value.c_str()));
        }

        if (secureLDAP && !fs::exists(tlsCacertFile.c_str()))
        {
            log<level::ERR>("LDAP server's CA certificate not provided",
                            entry("TLSCACERTFILE=%s", tlsCacertFile.c_str()));
            elog<NoCACertificate>();
        }
        val = ConfigIface::ldapServerURI(value);
        if (enabled())
        {
            writeConfig();
            parent.startOrStopService(nslcdService, enabled());
        }
        // save the object.
        serialize();
    }
    catch (const InternalFailure& e)
    {
        throw;
    }
    catch (const InvalidArgument& e)
    {
        throw;
    }
    catch (const NoCACertificate& e)
    {
        throw;
    }
    catch (const std::exception& e)
    {
        log<level::ERR>(e.what());
        elog<InternalFailure>();
    }
    return val;
}

std::string Config::ldapBindDN(std::string value)
{
    std::string val;
    try
    {
        if (value == ldapBindDN())
        {
            return value;
        }

        if (value.empty())
        {
            log<level::ERR>("Not a valid LDAP BINDDN",
                            entry("LDAPBINDDN=%s", value.c_str()));
            elog<InvalidArgument>(Argument::ARGUMENT_NAME("ldapBindDN"),
                                  Argument::ARGUMENT_VALUE(value.c_str()));
        }

        val = ConfigIface::ldapBindDN(value);
        if (enabled())
        {
            writeConfig();
            parent.startOrStopService(nslcdService, enabled());
        }
        // save the object.
        serialize();
    }
    catch (const InternalFailure& e)
    {
        throw;
    }
    catch (const InvalidArgument& e)
    {
        throw;
    }
    catch (const std::exception& e)
    {
        log<level::ERR>(e.what());
        elog<InternalFailure>();
    }
    return val;
}

std::string Config::ldapBaseDN(std::string value)
{
    std::string val;
    try
    {
        if (value == ldapBaseDN())
        {
            return value;
        }

        if (value.empty())
        {
            log<level::ERR>("Not a valid LDAP BASEDN",
                            entry("BASEDN=%s", value.c_str()));
            elog<InvalidArgument>(Argument::ARGUMENT_NAME("ldapBaseDN"),
                                  Argument::ARGUMENT_VALUE(value.c_str()));
        }

        val = ConfigIface::ldapBaseDN(value);
        if (enabled())
        {
            writeConfig();
            parent.startOrStopService(nslcdService, enabled());
        }
        // save the object.
        serialize();
    }
    catch (const InternalFailure& e)
    {
        throw;
    }
    catch (const InvalidArgument& e)
    {
        throw;
    }
    catch (const std::exception& e)
    {
        log<level::ERR>(e.what());
        elog<InternalFailure>();
    }
    return val;
}

ConfigIface::SearchScope Config::ldapSearchScope(ConfigIface::SearchScope value)
{
    ConfigIface::SearchScope val;
    try
    {
        if (value == ldapSearchScope())
        {
            return value;
        }

        val = ConfigIface::ldapSearchScope(value);
        if (enabled())
        {
            writeConfig();

            parent.startOrStopService(nslcdService, enabled());
        }
        // save the object.
        serialize();
    }
    catch (const InternalFailure& e)
    {
        throw;
    }
    catch (const std::exception& e)
    {
        log<level::ERR>(e.what());
        elog<InternalFailure>();
    }
    return val;
}

ConfigIface::Type Config::ldapType(ConfigIface::Type /*value*/)
{
    elog<NotAllowed>(NotAllowedArgument::REASON("ReadOnly Property"));
    return ldapType();
}

bool Config::enabled(bool value)
{
    if (value == enabled())
    {
        return value;
    }
    // Let parent decide that can we enable this config.
    // It may happen that other config is already enabled,
    // Current implementation support only one config can
    // be active at a time.
    return parent.enableService(*this, value);
}

bool Config::enableService(bool value)
{
    bool isEnable = false;
    try
    {
        isEnable = EnableIface::enabled(value);
        if (isEnable)
        {
            writeConfig();
        }
        parent.startOrStopService(nslcdService, value);
        serialize();
    }
    catch (const InternalFailure& e)
    {
        throw;
    }
    catch (const std::exception& e)
    {
        log<level::ERR>(e.what());
        elog<InternalFailure>();
    }
    return isEnable;
}

std::string Config::userNameAttribute(std::string value)
{
    std::string val;
    try
    {
        if (value == userNameAttribute())
        {
            return value;
        }

        val = ConfigIface::userNameAttribute(value);
        if (enabled())
        {
            writeConfig();

            parent.startOrStopService(nslcdService, enabled());
        }
        // save the object.
        serialize();
    }
    catch (const InternalFailure& e)
    {
        throw;
    }
    catch (const std::exception& e)
    {
        log<level::ERR>(e.what());
        elog<InternalFailure>();
    }
    return val;
}

std::string Config::groupNameAttribute(std::string value)
{
    std::string val;
    try
    {
        if (value == groupNameAttribute())
        {
            return value;
        }

        val = ConfigIface::groupNameAttribute(value);
        if (enabled())
        {
            writeConfig();

            parent.startOrStopService(nslcdService, enabled());
        }
        // save the object.
        serialize();
    }
    catch (const InternalFailure& e)
    {
        throw;
    }
    catch (const std::exception& e)
    {
        log<level::ERR>(e.what());
        elog<InternalFailure>();
    }
    return val;
}

template <class Archive>
void Config::save(Archive& archive, const std::uint32_t /*version*/) const
{
    archive(this->enabled());
    archive(ldapServerURI());
    archive(ldapBindDN());
    archive(ldapBaseDN());
    archive(ldapSearchScope());
    archive(ldapBindPassword);
    archive(userNameAttribute());
    archive(groupNameAttribute());
}

template <class Archive>
void Config::load(Archive& archive, const std::uint32_t /*version*/)
{
    bool bVal;
    archive(bVal);
    EnableIface::enabled(bVal);

    std::string str;
    archive(str);
    ConfigIface::ldapServerURI(str);

    archive(str);
    ConfigIface::ldapBindDN(str);

    archive(str);
    ConfigIface::ldapBaseDN(str);

    ConfigIface::SearchScope scope;
    archive(scope);
    ConfigIface::ldapSearchScope(scope);

    archive(str);
    ldapBindPassword = str;

    archive(str);
    ConfigIface::userNameAttribute(str);

    archive(str);
    ConfigIface::groupNameAttribute(str);
}

void Config::serialize()
{

    if (!fs::exists(configPersistPath.c_str()))
    {
        std::ofstream os(configPersistPath.string(),
                         std::ios::binary | std::ios::out);
        auto permission = fs::perms::owner_read | fs::perms::owner_write |
                          fs::perms::group_read;
        fs::permissions(configPersistPath, permission);
        cereal::BinaryOutputArchive oarchive(os);
        oarchive(*this);
    }
    else
    {
        std::ofstream os(configPersistPath.string(),
                         std::ios::binary | std::ios::out);
        cereal::BinaryOutputArchive oarchive(os);
        oarchive(*this);
    }
    return;
}

bool Config::deserialize()
{
    try
    {
        if (fs::exists(configPersistPath))
        {
            std::ifstream is(configPersistPath.c_str(),
                             std::ios::in | std::ios::binary);
            cereal::BinaryInputArchive iarchive(is);
            iarchive(*this);

            if (isValidLDAPURI(ldapServerURI(), LDAPscheme))
            {
                secureLDAP = false;
            }
            else if (isValidLDAPURI(ldapServerURI(), LDAPSscheme))
            {
                secureLDAP = true;
            }
            return true;
        }
        return false;
    }
    catch (const cereal::Exception& e)
    {
        log<level::ERR>(e.what());
        std::error_code ec;
        fs::remove(configPersistPath, ec);
        return false;
    }
    catch (const fs::filesystem_error& e)
    {
        return false;
    }
}

ObjectPath Config::create(std::string groupName, std::string privilege)
{
    checkPrivilegeMapper(groupName);
    checkPrivilegeLevel(privilege);

    entryId++;

    // Object path for the LDAP group privilege mapper entry
    fs::path mapperObjectPath = objectPath;
    mapperObjectPath /= "role_map";
    mapperObjectPath /= std::to_string(entryId);

    fs::path persistPath = parent.dbusPersistentPath;
    persistPath += mapperObjectPath;

    // Create mapping for LDAP privilege mapper entry
    auto entry = std::make_unique<LDAPMapperEntry>(
        bus, mapperObjectPath.string().c_str(), persistPath.string().c_str(),
        groupName, privilege, *this);

    phosphor::ldap::serialize(*entry, std::move(persistPath));

    PrivilegeMapperList.emplace(entryId, std::move(entry));
    return mapperObjectPath.string();
}

void Config::deletePrivilegeMapper(Id id)
{
    fs::path mapperObjectPath = objectPath;
    mapperObjectPath /= "role_map";
    mapperObjectPath /= std::to_string(id);

    fs::path persistPath = parent.dbusPersistentPath;
    persistPath += std::move(mapperObjectPath);

    // Delete the persistent representation of the privilege mapper.
    fs::remove(std::move(persistPath));

    PrivilegeMapperList.erase(id);
}
void Config::checkPrivilegeMapper(const std::string& groupName)
{
    if (groupName.empty())
    {
        log<level::ERR>("Group name is empty");
        elog<InvalidArgument>(Argument::ARGUMENT_NAME("Group name"),
                              Argument::ARGUMENT_VALUE("Null"));
    }

    for (const auto& val : PrivilegeMapperList)
    {
        if (val.second.get()->groupName() == groupName)
        {
            log<level::ERR>("Group name already exists");
            elog<PrivilegeMappingExists>();
        }
    }
}

void Config::checkPrivilegeLevel(const std::string& privilege)
{
    if (privilege.empty())
    {
        log<level::ERR>("Privilege level is empty");
        elog<InvalidArgument>(Argument::ARGUMENT_NAME("Privilege level"),
                              Argument::ARGUMENT_VALUE("Null"));
    }

    if (std::find(privMgr.begin(), privMgr.end(), privilege) == privMgr.end())
    {
        log<level::ERR>("Invalid privilege");
        elog<InvalidArgument>(Argument::ARGUMENT_NAME("Privilege level"),
                              Argument::ARGUMENT_VALUE(privilege.c_str()));
    }
}

void Config::restoreRoleMapping()
{
    namespace fs = std::filesystem;
    fs::path dir = parent.dbusPersistentPath;
    dir += objectPath;
    dir /= "role_map";

    if (!fs::exists(dir) || fs::is_empty(dir))
    {
        return;
    }

    for (auto& file : fs::directory_iterator(dir))
    {
        std::string id = file.path().filename().c_str();
        size_t idNum = std::stol(id);

        auto entryPath = objectPath + '/' + "role_map" + '/' + id;
        auto persistPath = parent.dbusPersistentPath + entryPath;
        auto entry = std::make_unique<LDAPMapperEntry>(
            bus, entryPath.c_str(), persistPath.c_str(), *this);
        if (phosphor::ldap::deserialize(file.path(), *entry))
        {
            entry->Interfaces::emit_object_added();
            PrivilegeMapperList.emplace(idNum, std::move(entry));
            if (idNum > entryId)
            {
                entryId = idNum;
            }
        }
    }
}

} // namespace ldap
} // namespace phosphor
