diff options
author | Nagaraju Goruganti <ngorugan@in.ibm.com> | 2018-09-18 05:05:50 -0500 |
---|---|---|
committer | Brad Bishop <bradleyb@fuzziesquirrel.com> | 2018-10-04 15:14:12 -0400 |
commit | f1940d9e431eecfd900b2532d1255709fa416814 (patch) | |
tree | 5150294b6c17010ddf73d3b2956c504aa5836ecc /phosphor-ldap-config | |
parent | 997f5e0087568a17dc1434fdaccb553dbcaa7b0e (diff) | |
download | phosphor-user-manager-f1940d9e431eecfd900b2532d1255709fa416814.tar.gz phosphor-user-manager-f1940d9e431eecfd900b2532d1255709fa416814.zip |
phosphor-ldap-conf: implement restore and add error handling
Upon startup, restore D-Bus properties from LDAP config file if
it exists.
Change-Id: I63b5a41eec8937ddbd5e8b4471936376602b6b0e
Signed-off-by: Nagaraju Goruganti <ngorugan@in.ibm.com>
Diffstat (limited to 'phosphor-ldap-config')
-rw-r--r-- | phosphor-ldap-config/ldap_configuration.cpp | 359 | ||||
-rw-r--r-- | phosphor-ldap-config/ldap_configuration.hpp | 30 |
2 files changed, 327 insertions, 62 deletions
diff --git a/phosphor-ldap-config/ldap_configuration.cpp b/phosphor-ldap-config/ldap_configuration.cpp index 06a4d5d..6680541 100644 --- a/phosphor-ldap-config/ldap_configuration.cpp +++ b/phosphor-ldap-config/ldap_configuration.cpp @@ -1,7 +1,5 @@ -#include <phosphor-logging/elog.hpp> -#include <phosphor-logging/elog-errors.hpp> #include "ldap_configuration.hpp" -#include "config.h" +#include <experimental/filesystem> #include <fstream> #include <sstream> @@ -11,6 +9,15 @@ namespace ldap { constexpr auto nslcdService = "nslcd.service"; +using namespace phosphor::logging; +using namespace sdbusplus::xyz::openbmc_project::Common::Error; +namespace fs = std::experimental::filesystem; + +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, bool secureLDAP, std::string lDAPServerURI, std::string lDAPBindDN, std::string lDAPBaseDN, @@ -35,7 +42,6 @@ Config::Config(sdbusplus::bus::bus& bus, const char* path, const char* filePath, void Config::writeConfig() { - std::fstream stream(configFilePath.c_str(), std::fstream::out); std::stringstream confData; confData << "uid root\n"; confData << "gid root\n\n"; @@ -97,117 +103,221 @@ void Config::writeConfig() confData << "map passwd uid cn\n"; confData << "map passwd gecos displayName\n"; } - stream << confData.str(); - stream.flush(); - stream.close(); + try + { + std::fstream stream(configFilePath.c_str(), std::fstream::out); + stream << confData.str(); + stream.flush(); + stream.close(); + } + catch (const std::exception& e) + { + log<level::ERR>(e.what()); + elog<InternalFailure>(); + } return; } bool Config::secureLDAP(bool value) { - if (value == secureLDAP()) + bool val = false; + try { - return value; - } + if (value == secureLDAP()) + { + return value; + } - auto val = ConfigIface::secureLDAP(value); - writeConfig(); - parent.restartService(nslcdService); + val = ConfigIface::secureLDAP(value); + writeConfig(); + parent.restartService(nslcdService); + } + catch (const InternalFailure& e) + { + throw; + } + catch (const std::exception& e) + { + log<level::ERR>(e.what()); + elog<InternalFailure>(); + } return val; } std::string Config::lDAPServerURI(std::string value) { - if (value == lDAPServerURI()) + std::string val; + try { - return value; - } + if (value == lDAPServerURI()) + { + return value; + } - auto val = ConfigIface::lDAPServerURI(value); - writeConfig(); - parent.restartService(nslcdService); + val = ConfigIface::lDAPServerURI(value); + writeConfig(); + parent.restartService(nslcdService); + } + catch (const InternalFailure& e) + { + throw; + } + catch (const std::exception& e) + { + log<level::ERR>(e.what()); + elog<InternalFailure>(); + } return val; } std::string Config::lDAPBindDN(std::string value) { - if (value == lDAPBindDN()) + std::string val; + try { - return value; - } - - auto val = ConfigIface::lDAPBindDN(value); - writeConfig(); - parent.restartService(nslcdService); + if (value == lDAPBindDN()) + { + return value; + } + val = ConfigIface::lDAPBindDN(value); + writeConfig(); + parent.restartService(nslcdService); + } + catch (const InternalFailure& e) + { + throw; + } + catch (const std::exception& e) + { + log<level::ERR>(e.what()); + elog<InternalFailure>(); + } return val; } std::string Config::lDAPBaseDN(std::string value) { - if (value == lDAPBaseDN()) + std::string val; + try { - return value; - } - - auto val = ConfigIface::lDAPBaseDN(value); - writeConfig(); - parent.restartService(nslcdService); + if (value == lDAPBaseDN()) + { + return value; + } + val = ConfigIface::lDAPBaseDN(value); + writeConfig(); + parent.restartService(nslcdService); + } + catch (const InternalFailure& e) + { + throw; + } + catch (const std::exception& e) + { + log<level::ERR>(e.what()); + elog<InternalFailure>(); + } return val; } std::string Config::lDAPBINDDNpassword(std::string value) { - if (value == lDAPBINDDNpassword()) + std::string val; + try { - return value; - } - - auto val = ConfigIface::lDAPBINDDNpassword(value); - writeConfig(); - parent.restartService(nslcdService); + if (value == lDAPBINDDNpassword()) + { + return value; + } + val = ConfigIface::lDAPBINDDNpassword(value); + writeConfig(); + parent.restartService(nslcdService); + } + catch (const InternalFailure& e) + { + throw; + } + catch (const std::exception& e) + { + log<level::ERR>(e.what()); + elog<InternalFailure>(); + } return val; } ldap_base::Config::SearchScope Config::lDAPSearchScope(ldap_base::Config::SearchScope value) { - if (value == lDAPSearchScope()) + ldap_base::Config::SearchScope val; + try { - return value; - } - - auto val = ConfigIface::lDAPSearchScope(value); - writeConfig(); - parent.restartService(nslcdService); + if (value == lDAPSearchScope()) + { + return value; + } + val = ConfigIface::lDAPSearchScope(value); + writeConfig(); + parent.restartService(nslcdService); + } + catch (const InternalFailure& e) + { + throw; + } + catch (const std::exception& e) + { + log<level::ERR>(e.what()); + elog<InternalFailure>(); + } return val; } ldap_base::Config::Type Config::lDAPType(ldap_base::Config::Type value) { - if (value == lDAPType()) + ldap_base::Config::Type val; + try { - return value; - } - - auto val = ConfigIface::lDAPType(value); - writeConfig(); - parent.restartService(nslcdService); + if (value == lDAPType()) + { + return value; + } + val = ConfigIface::lDAPType(value); + writeConfig(); + parent.restartService(nslcdService); + } + catch (const InternalFailure& e) + { + throw; + } + catch (const std::exception& e) + { + log<level::ERR>(e.what()); + elog<InternalFailure>(); + } return val; } void ConfigMgr::restartService(const std::string& service) { - auto method = bus.new_method_call(SYSTEMD_BUSNAME, SYSTEMD_PATH, - SYSTEMD_INTERFACE, "RestartUnit"); - method.append(service.c_str(), "replace"); - bus.call_noreply(method); + try + { + auto method = bus.new_method_call(SYSTEMD_BUSNAME, SYSTEMD_PATH, + SYSTEMD_INTERFACE, "RestartUnit"); + method.append(service.c_str(), "replace"); + bus.call_noreply(method); + } + catch (const sdbusplus::exception::SdBusError& ex) + { + log<level::ERR>("Failed to restart nslcd service", + entry("ERR=%s", ex.what())); + elog<InternalFailure>(); + } } std::string @@ -217,6 +327,7 @@ std::string ldap_base::Create::SearchScope lDAPSearchScope, ldap_base::Create::Type lDAPType) { + // TODO Validate parameters passed-in. // With current implementation we support only one LDAP server. configPtr.reset(nullptr); @@ -230,5 +341,137 @@ std::string return objPath; } +void ConfigMgr::restore(const char* filePath) +{ + if (!fs::exists(filePath)) + { + log<level::ERR>("Config file doesn't exists", + entry("LDAP_CONFIG_FILE=%s", LDAP_CONFIG_FILE)); + return; + } + + ConfigInfo configValues; + + try + { + std::fstream stream(filePath, std::fstream::in); + Line line; + // read characters from stream and places them into line + while (std::getline(stream, line)) + { + // remove leading and trailing extra spaces + auto firstScan = line.find_first_not_of(' '); + auto first = + (firstScan == std::string::npos ? line.length() : firstScan); + auto last = line.find_last_not_of(' '); + line = line.substr(first, last - first + 1); + // reduce multiple spaces between two words to a single space + auto pred = [](char a, char b) { + return (a == b && a == ' ') ? true : false; + }; + + auto lastPos = std::unique(line.begin(), line.end(), pred); + + line.erase(lastPos, line.end()); + + // Ignore if line is empty or starts with '#' + if (line.empty() || line.at(0) == '#') + { + continue; + } + + Key key; + std::istringstream isLine(line); + // extract characters from isLine and stores them into + // key until the delimitation character ' ' is found. + // If the delimiter is found, it is extracted and discarded + // the next input operation will begin after it. + if (std::getline(isLine, key, ' ')) + { + Val value; + // extract characters after delimitation character ' ' + if (std::getline(isLine, value, ' ')) + { + // skip line if it starts with "base shadow" or + // "base passwd" because we would have 3 entries + // ("base lDAPBaseDN" , "base passwd lDAPBaseDN" and + // "base shadow lDAPBaseDN") for the property "lDAPBaseDN", + // one is enough to restore it. + + if ((key == "base") && + (value == "passwd" || value == "shadow")) + { + continue; + } + // skip the line if it starts with "map passwd". + // if config type is AD "map group" entry would be add to + // the map configValues. For OpenLdap config file no map + // entry would be there. + if ((key == "map") && (value == "passwd")) + { + continue; + } + configValues[key] = value; + } + } + } + + // extract properties from configValues map + bool secureLDAP; + if (configValues["ssl"] == "on") + { + secureLDAP = true; + } + else + { + secureLDAP = false; + } + + ldap_base::Create::SearchScope lDAPSearchScope; + if (configValues["scope"] == "sub") + { + lDAPSearchScope = ldap_base::Create::SearchScope::sub; + } + else if (configValues["scope"] == "one") + { + lDAPSearchScope = ldap_base::Create::SearchScope::one; + } + else + { + lDAPSearchScope = ldap_base::Create::SearchScope::base; + } + + ldap_base::Create::Type lDAPType; + // If the file is having a line which starts with "map group" + if (configValues["map"] == "group") + { + lDAPType = ldap_base::Create::Type::ActiveDirectory; + } + else + { + lDAPType = ldap_base::Create::Type::OpenLdap; + } + + createConfig( + secureLDAP, std::move(configValues["uri"]), + std::move(configValues["binddn"]), std::move(configValues["base"]), + std::move(configValues["bindpw"]), lDAPSearchScope, lDAPType); + } + catch (const InvalidArgument& e) + { + // Don't throw - we don't want to create a D-Bus + // object upon finding empty values in config, as + // this can be a default config. + } + catch (const InternalFailure& e) + { + throw; + } + catch (const std::exception& e) + { + log<level::ERR>(e.what()); + elog<InternalFailure>(); + } +} } // namespace ldap } // namespace phosphor diff --git a/phosphor-ldap-config/ldap_configuration.hpp b/phosphor-ldap-config/ldap_configuration.hpp index f2bf02a..a0324c1 100644 --- a/phosphor-ldap-config/ldap_configuration.hpp +++ b/phosphor-ldap-config/ldap_configuration.hpp @@ -1,9 +1,14 @@ #pragma once -#include <sdbusplus/bus.hpp> -#include <sdbusplus/server/object.hpp> +#include "config.h" #include <xyz/openbmc_project/User/Ldap/Config/server.hpp> #include <xyz/openbmc_project/User/Ldap/Create/server.hpp> +#include <xyz/openbmc_project/Common/error.hpp> +#include <phosphor-logging/log.hpp> +#include <phosphor-logging/elog.hpp> +#include <phosphor-logging/elog-errors.hpp> +#include <sdbusplus/bus.hpp> +#include <sdbusplus/server/object.hpp> #include <string> namespace phosphor @@ -15,6 +20,8 @@ static constexpr auto nsSwitchFile = "/etc/nsswitch.conf"; static constexpr auto LDAPNsSwitchFile = "/etc/nsswitch_ldap.conf"; static constexpr auto linuxNsSwitchFile = "/etc/nsswitch_linux.conf"; +using namespace phosphor::logging; +using namespace sdbusplus::xyz::openbmc_project::Common::Error; namespace ldap_base = sdbusplus::xyz::openbmc_project::User::Ldap::server; using ConfigIface = sdbusplus::server::object::object<ldap_base::Config>; using CreateIface = sdbusplus::server::object::object<ldap_base::Create>; @@ -144,9 +151,19 @@ class ConfigMgr : public CreateIface * @param[in] filePath - LDAP configuration file. */ ConfigMgr(sdbusplus::bus::bus& bus, const char* path) : - CreateIface(bus, path), bus(bus) + CreateIface(bus, path, true), bus(bus) { - // TODO restore config object if config file exists. + try + { + restore(LDAP_CONFIG_FILE); + emit_object_added(); + } + catch (const std::exception& e) + { + configPtr.reset(nullptr); + log<level::ERR>(e.what()); + elog<InternalFailure>(); + } } /** @brief concrete implementation of the pure virtual funtion @@ -179,6 +196,11 @@ class ConfigMgr : public CreateIface /** @brief Pointer to a Config D-Bus object */ std::unique_ptr<Config> configPtr = nullptr; + + /** @brief Populate existing config into D-Bus properties + * @param[in] filePath - LDAP config file path + */ + virtual void restore(const char* filePath); }; } // namespace ldap } // namespace phosphor |