Change the name of the files to make it align with other filenames
TestedBy: Unit-Tested
Signed-off-by: Ratan Gupta <ratagupt@linux.vnet.ibm.com>
Change-Id: I657962e8cb06b083877321e27cd0c94644e1ebcb
diff --git a/phosphor-ldap-config/ldap_config.cpp b/phosphor-ldap-config/ldap_config.cpp
new file mode 100644
index 0000000..d10a711
--- /dev/null
+++ b/phosphor-ldap-config/ldap_config.cpp
@@ -0,0 +1,486 @@
+#include "ldap_config_mgr.hpp"
+#include "ldap_config.hpp"
+#include "ldap_config_serialize.hpp"
+#include "utils.hpp"
+#include <filesystem>
+#include <fstream>
+#include <sstream>
+
+namespace phosphor
+{
+namespace ldap
+{
+
+constexpr auto nslcdService = "nslcd.service";
+constexpr auto nscdService = "nscd.service";
+constexpr auto LDAPscheme = "ldap";
+constexpr auto LDAPSscheme = "ldaps";
+
+using namespace phosphor::logging;
+using namespace sdbusplus::xyz::openbmc_project::Common::Error;
+namespace fs = std::filesystem;
+using Argument = xyz::openbmc_project::Common::InvalidArgument;
+
+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, 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, true),
+ secureLDAP(secureLDAP), lDAPBindPassword(std::move(lDAPBindDNPassword)),
+ configFilePath(filePath), tlsCacertFile(caCertFile), bus(bus),
+ parent(parent)
+{
+ ConfigIface::lDAPServerURI(lDAPServerURI);
+ ConfigIface::lDAPBindDN(lDAPBindDN);
+ ConfigIface::lDAPBaseDN(lDAPBaseDN);
+ ConfigIface::lDAPSearchScope(lDAPSearchScope);
+ ConfigIface::lDAPType(lDAPType);
+ EnableIface::enabled(lDAPServiceEnabled);
+ ConfigIface::userNameAttribute(userNameAttr);
+ ConfigIface::groupNameAttribute(groupNameAttr);
+ // Don't update the bindDN password under ConfigIface::
+ writeConfig();
+ // Emit deferred signal.
+ this->emit_object_added();
+ parent.startOrStopService(nslcdService, enabled());
+}
+
+void Config::delete_()
+{
+ parent.deleteObject();
+ try
+ {
+ fs::path configDir = fs::path(configFilePath.c_str()).parent_path();
+
+ fs::copy_file(configDir / defaultNslcdFile, LDAP_CONFIG_FILE,
+ fs::copy_options::overwrite_existing);
+ }
+ catch (const std::exception& e)
+ {
+ log<level::ERR>("Failed to rename Config Files while deleting Object",
+ entry("ERR=%s", e.what()));
+ elog<InternalFailure>();
+ }
+
+ parent.restartService(nscdService);
+ parent.stopService(nslcdService);
+}
+
+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";
+ confData << "tls_cacertFile " << tlsCacertFile.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";
+ }
+ 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";
+ }
+ 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
+ {
+ writeConfig();
+ parent.startOrStopService(nslcdService, enabled());
+ }
+ 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);
+ writeConfig();
+ parent.startOrStopService(nslcdService, enabled());
+ }
+ 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);
+ writeConfig();
+ parent.startOrStopService(nslcdService, enabled());
+ }
+ 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);
+ writeConfig();
+ parent.startOrStopService(nslcdService, enabled());
+ }
+ 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);
+ writeConfig();
+ parent.startOrStopService(nslcdService, enabled());
+ }
+ 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)
+{
+ ConfigIface::Type val;
+ try
+ {
+ if (value == lDAPType())
+ {
+ return value;
+ }
+
+ val = ConfigIface::lDAPType(value);
+ writeConfig();
+ parent.startOrStopService(nslcdService, enabled());
+ }
+ catch (const InternalFailure& e)
+ {
+ throw;
+ }
+ catch (const std::exception& e)
+ {
+ log<level::ERR>(e.what());
+ elog<InternalFailure>();
+ }
+ return val;
+}
+
+bool Config::enabled(bool value)
+{
+ bool isEnable;
+ try
+ {
+ if (value == enabled())
+ {
+ return value;
+ }
+ isEnable = EnableIface::enabled(value);
+ // save the enabled property.
+ serialize(*this, parent.dbusPersistentPath);
+ parent.startOrStopService(nslcdService, value);
+ }
+ 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);
+ writeConfig();
+ parent.startOrStopService(nslcdService, enabled());
+ }
+ 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);
+ writeConfig();
+ parent.startOrStopService(nslcdService, enabled());
+ }
+ catch (const InternalFailure& e)
+ {
+ throw;
+ }
+ catch (const std::exception& e)
+ {
+ log<level::ERR>(e.what());
+ elog<InternalFailure>();
+ }
+ return val;
+}
+
+} // namespace ldap
+} // namespace phosphor