1e1f4db62SRatan Gupta #include "ldap_config_mgr.hpp"
2e1f4db62SRatan Gupta
39638afb9SPatrick Williams #include "ldap_config.hpp"
4e1f4db62SRatan Gupta #include "utils.hpp"
59638afb9SPatrick Williams
6e8d664d1SJiaqing Zhao #include <phosphor-logging/elog-errors.hpp>
7e8d664d1SJiaqing Zhao #include <phosphor-logging/elog.hpp>
8e8d664d1SJiaqing Zhao #include <phosphor-logging/lg2.hpp>
9e8d664d1SJiaqing Zhao #include <xyz/openbmc_project/Common/error.hpp>
10e8d664d1SJiaqing Zhao
11e1f4db62SRatan Gupta #include <filesystem>
12e1f4db62SRatan Gupta #include <fstream>
13e1f4db62SRatan Gupta #include <sstream>
14e1f4db62SRatan Gupta
15e1f4db62SRatan Gupta namespace phosphor
16e1f4db62SRatan Gupta {
17e1f4db62SRatan Gupta namespace ldap
18e1f4db62SRatan Gupta {
19e1f4db62SRatan Gupta
20*af1594c9SRavi Teja constexpr auto systemdBusname = "org.freedesktop.systemd1";
21*af1594c9SRavi Teja constexpr auto systemdObjPath = "/org/freedesktop/systemd1";
22*af1594c9SRavi Teja constexpr auto systemdInterface = "org.freedesktop.systemd1.Manager";
23*af1594c9SRavi Teja
24372c5668SAlexander Filippov constexpr auto nslcdService = "nslcd.service";
25e1f4db62SRatan Gupta constexpr auto nscdService = "nscd.service";
2678d85042SNan Zhou constexpr auto ldapScheme = "ldap";
2778d85042SNan Zhou constexpr auto ldapsScheme = "ldaps";
28e1f4db62SRatan Gupta
29e8d664d1SJiaqing Zhao using namespace phosphor::logging;
30e1f4db62SRatan Gupta using namespace sdbusplus::xyz::openbmc_project::Common::Error;
31e1f4db62SRatan Gupta namespace fs = std::filesystem;
32e1f4db62SRatan Gupta using Argument = xyz::openbmc_project::Common::InvalidArgument;
33c5481d1cSRatan Gupta using NotAllowedArgument = xyz::openbmc_project::Common::NotAllowed;
34e1f4db62SRatan Gupta
35e1f4db62SRatan Gupta using Line = std::string;
36e1f4db62SRatan Gupta using Key = std::string;
37e1f4db62SRatan Gupta using Val = std::string;
38e1f4db62SRatan Gupta using ConfigInfo = std::map<Key, Val>;
39e1f4db62SRatan Gupta
startOrStopService(const std::string & service,bool start)40e1f4db62SRatan Gupta void ConfigMgr::startOrStopService(const std::string& service, bool start)
41e1f4db62SRatan Gupta {
42e1f4db62SRatan Gupta if (start)
43e1f4db62SRatan Gupta {
44e1f4db62SRatan Gupta restartService(service);
45e1f4db62SRatan Gupta }
46e1f4db62SRatan Gupta else
47e1f4db62SRatan Gupta {
48e1f4db62SRatan Gupta stopService(service);
49e1f4db62SRatan Gupta }
50e1f4db62SRatan Gupta }
51e1f4db62SRatan Gupta
restartService(const std::string & service)52e1f4db62SRatan Gupta void ConfigMgr::restartService(const std::string& service)
53e1f4db62SRatan Gupta {
54e1f4db62SRatan Gupta try
55e1f4db62SRatan Gupta {
56*af1594c9SRavi Teja auto method = bus.new_method_call(systemdBusname, systemdObjPath,
57*af1594c9SRavi Teja systemdInterface, "RestartUnit");
58e1f4db62SRatan Gupta method.append(service.c_str(), "replace");
59e1f4db62SRatan Gupta bus.call_noreply(method);
60e1f4db62SRatan Gupta }
61b3ef4e1aSPatrick Williams catch (const sdbusplus::exception_t& ex)
62e1f4db62SRatan Gupta {
6311ec666bSJiaqing Zhao lg2::error("Failed to restart service {SERVICE}: {ERR}", "SERVICE",
6411ec666bSJiaqing Zhao service, "ERR", ex);
65e1f4db62SRatan Gupta elog<InternalFailure>();
66e1f4db62SRatan Gupta }
67e1f4db62SRatan Gupta }
stopService(const std::string & service)68e1f4db62SRatan Gupta void ConfigMgr::stopService(const std::string& service)
69e1f4db62SRatan Gupta {
70e1f4db62SRatan Gupta try
71e1f4db62SRatan Gupta {
72*af1594c9SRavi Teja auto method = bus.new_method_call(systemdBusname, systemdObjPath,
73*af1594c9SRavi Teja systemdInterface, "StopUnit");
74e1f4db62SRatan Gupta method.append(service.c_str(), "replace");
75e1f4db62SRatan Gupta bus.call_noreply(method);
76e1f4db62SRatan Gupta }
77b3ef4e1aSPatrick Williams catch (const sdbusplus::exception_t& ex)
78e1f4db62SRatan Gupta {
7911ec666bSJiaqing Zhao lg2::error("Failed to stop service {SERVICE}: {ERR}", "SERVICE",
8011ec666bSJiaqing Zhao service, "ERR", ex);
81e1f4db62SRatan Gupta elog<InternalFailure>();
82e1f4db62SRatan Gupta }
83e1f4db62SRatan Gupta }
84e1f4db62SRatan Gupta
createConfig(std::string ldapServerURI,std::string ldapBindDN,std::string ldapBaseDN,std::string ldapBindDNPassword,CreateIface::SearchScope ldapSearchScope,CreateIface::Create::Type ldapType,std::string groupNameAttribute,std::string userNameAttribute)85e1f4db62SRatan Gupta std::string ConfigMgr::createConfig(
86e6500a49SPatrick Williams std::string ldapServerURI, std::string ldapBindDN, std::string ldapBaseDN,
87e6500a49SPatrick Williams std::string ldapBindDNPassword, CreateIface::SearchScope ldapSearchScope,
88e6500a49SPatrick Williams CreateIface::Create::Type ldapType, std::string groupNameAttribute,
89e1f4db62SRatan Gupta std::string userNameAttribute)
90e1f4db62SRatan Gupta {
91e1f4db62SRatan Gupta bool secureLDAP = false;
92e1f4db62SRatan Gupta
9378d85042SNan Zhou if (isValidLDAPURI(ldapServerURI, ldapsScheme))
94e1f4db62SRatan Gupta {
95e1f4db62SRatan Gupta secureLDAP = true;
96e1f4db62SRatan Gupta }
9778d85042SNan Zhou else if (isValidLDAPURI(ldapServerURI, ldapScheme))
98e1f4db62SRatan Gupta {
99e1f4db62SRatan Gupta secureLDAP = false;
100e1f4db62SRatan Gupta }
101e1f4db62SRatan Gupta else
102e1f4db62SRatan Gupta {
10311ec666bSJiaqing Zhao lg2::error("Bad LDAP Server URI {URI}", "URI", ldapServerURI);
104e6500a49SPatrick Williams elog<InvalidArgument>(Argument::ARGUMENT_NAME("ldapServerURI"),
105e6500a49SPatrick Williams Argument::ARGUMENT_VALUE(ldapServerURI.c_str()));
106e1f4db62SRatan Gupta }
107e1f4db62SRatan Gupta
108e1f4db62SRatan Gupta if (secureLDAP && !fs::exists(tlsCacertFile.c_str()))
109e1f4db62SRatan Gupta {
11011ec666bSJiaqing Zhao lg2::error("LDAP server CA certificate not found at {PATH}", "PATH",
11111ec666bSJiaqing Zhao tlsCacertFile);
112e1f4db62SRatan Gupta elog<NoCACertificate>();
113e1f4db62SRatan Gupta }
114e1f4db62SRatan Gupta
115e6500a49SPatrick Williams if (ldapBindDN.empty())
116e1f4db62SRatan Gupta {
11711ec666bSJiaqing Zhao lg2::error("'{BINDDN}' is not a valid LDAP BindDN", "BINDDN",
11811ec666bSJiaqing Zhao ldapBindDN);
119e1f4db62SRatan Gupta elog<InvalidArgument>(Argument::ARGUMENT_NAME("LDAPBindDN"),
120e6500a49SPatrick Williams Argument::ARGUMENT_VALUE(ldapBindDN.c_str()));
121e1f4db62SRatan Gupta }
122e1f4db62SRatan Gupta
123e6500a49SPatrick Williams if (ldapBaseDN.empty())
124e1f4db62SRatan Gupta {
12511ec666bSJiaqing Zhao lg2::error("'{BASEDN}' is not a valid LDAP BaseDN", "BASEDN",
12611ec666bSJiaqing Zhao ldapBaseDN);
127e1f4db62SRatan Gupta elog<InvalidArgument>(Argument::ARGUMENT_NAME("LDAPBaseDN"),
128e6500a49SPatrick Williams Argument::ARGUMENT_VALUE(ldapBaseDN.c_str()));
129e1f4db62SRatan Gupta }
130e1f4db62SRatan Gupta
13127d4c011SRatan Gupta // With current implementation we support only two default LDAP server.
13227d4c011SRatan Gupta // which will be always there but when the support comes for additional
13327d4c011SRatan Gupta // account providers then the create config would be used to create the
13427d4c011SRatan Gupta // additional config.
135e1f4db62SRatan Gupta
13627d4c011SRatan Gupta std::string objPath;
13727d4c011SRatan Gupta
138e6500a49SPatrick Williams if (static_cast<ConfigIface::Type>(ldapType) == ConfigIface::Type::OpenLdap)
13927d4c011SRatan Gupta {
14027d4c011SRatan Gupta openLDAPConfigPtr.reset(nullptr);
14127d4c011SRatan Gupta objPath = openLDAPDbusObjectPath;
14227d4c011SRatan Gupta openLDAPConfigPtr = std::make_unique<Config>(
143e1f4db62SRatan Gupta bus, objPath.c_str(), configFilePath.c_str(), tlsCacertFile.c_str(),
144e6500a49SPatrick Williams tlsCertFile.c_str(), secureLDAP, ldapServerURI, ldapBindDN,
145e6500a49SPatrick Williams ldapBaseDN, std::move(ldapBindDNPassword),
146e6500a49SPatrick Williams static_cast<ConfigIface::SearchScope>(ldapSearchScope),
147e6500a49SPatrick Williams static_cast<ConfigIface::Type>(ldapType), false, groupNameAttribute,
148e1f4db62SRatan Gupta userNameAttribute, *this);
14927d4c011SRatan Gupta }
15027d4c011SRatan Gupta else
15127d4c011SRatan Gupta {
15227d4c011SRatan Gupta ADConfigPtr.reset(nullptr);
15378d85042SNan Zhou objPath = adDbusObjectPath;
15427d4c011SRatan Gupta ADConfigPtr = std::make_unique<Config>(
15527d4c011SRatan Gupta bus, objPath.c_str(), configFilePath.c_str(), tlsCacertFile.c_str(),
156e6500a49SPatrick Williams tlsCertFile.c_str(), secureLDAP, ldapServerURI, ldapBindDN,
157e6500a49SPatrick Williams ldapBaseDN, std::move(ldapBindDNPassword),
158e6500a49SPatrick Williams static_cast<ConfigIface::SearchScope>(ldapSearchScope),
159e6500a49SPatrick Williams static_cast<ConfigIface::Type>(ldapType), false, groupNameAttribute,
16027d4c011SRatan Gupta userNameAttribute, *this);
16127d4c011SRatan Gupta }
162e1f4db62SRatan Gupta restartService(nscdService);
163e1f4db62SRatan Gupta return objPath;
164e1f4db62SRatan Gupta }
165e1f4db62SRatan Gupta
createDefaultObjects()16627d4c011SRatan Gupta void ConfigMgr::createDefaultObjects()
167e1f4db62SRatan Gupta {
16827d4c011SRatan Gupta if (!openLDAPConfigPtr)
169e1f4db62SRatan Gupta {
17027d4c011SRatan Gupta openLDAPConfigPtr = std::make_unique<Config>(
17127d4c011SRatan Gupta bus, openLDAPDbusObjectPath.c_str(), configFilePath.c_str(),
172ab4fcb4cSRatan Gupta tlsCacertFile.c_str(), tlsCertFile.c_str(),
173ab4fcb4cSRatan Gupta ConfigIface::Type::OpenLdap, *this);
17421e88cb5SRatan Gupta openLDAPConfigPtr->emit_object_added();
175e1f4db62SRatan Gupta }
17627d4c011SRatan Gupta if (!ADConfigPtr)
177e1f4db62SRatan Gupta {
17827d4c011SRatan Gupta ADConfigPtr = std::make_unique<Config>(
17978d85042SNan Zhou bus, adDbusObjectPath.c_str(), configFilePath.c_str(),
180ab4fcb4cSRatan Gupta tlsCacertFile.c_str(), tlsCertFile.c_str(),
181ab4fcb4cSRatan Gupta ConfigIface::Type::ActiveDirectory, *this);
18221e88cb5SRatan Gupta ADConfigPtr->emit_object_added();
18321e88cb5SRatan Gupta }
18421e88cb5SRatan Gupta }
18521e88cb5SRatan Gupta
enableService(Config & config,bool value)186c5481d1cSRatan Gupta bool ConfigMgr::enableService(Config& config, bool value)
187c5481d1cSRatan Gupta {
188c5481d1cSRatan Gupta if (value)
189c5481d1cSRatan Gupta {
190c5481d1cSRatan Gupta if (openLDAPConfigPtr && openLDAPConfigPtr->enabled())
191c5481d1cSRatan Gupta {
192c5481d1cSRatan Gupta elog<NotAllowed>(NotAllowedArgument::REASON(
193c5481d1cSRatan Gupta "OpenLDAP service is already active"));
194c5481d1cSRatan Gupta }
195c5481d1cSRatan Gupta if (ADConfigPtr && ADConfigPtr->enabled())
196c5481d1cSRatan Gupta {
197c5481d1cSRatan Gupta elog<NotAllowed>(NotAllowedArgument::REASON(
198c5481d1cSRatan Gupta "ActiveDirectory service is already active"));
199c5481d1cSRatan Gupta }
200c5481d1cSRatan Gupta }
201c5481d1cSRatan Gupta return config.enableService(value);
202c5481d1cSRatan Gupta }
203c5481d1cSRatan Gupta
restore()20421e88cb5SRatan Gupta void ConfigMgr::restore()
20521e88cb5SRatan Gupta {
20621e88cb5SRatan Gupta createDefaultObjects();
20721e88cb5SRatan Gupta // Restore the ldap config and their mappings
20821e88cb5SRatan Gupta if (ADConfigPtr->deserialize())
20921e88cb5SRatan Gupta {
2107b04c352SRatan Gupta // Restore the role mappings
2117b04c352SRatan Gupta ADConfigPtr->restoreRoleMapping();
21221e88cb5SRatan Gupta ADConfigPtr->emit_object_added();
21321e88cb5SRatan Gupta }
21421e88cb5SRatan Gupta if (openLDAPConfigPtr->deserialize())
21521e88cb5SRatan Gupta {
2167b04c352SRatan Gupta // Restore the role mappings
2177b04c352SRatan Gupta openLDAPConfigPtr->restoreRoleMapping();
21821e88cb5SRatan Gupta openLDAPConfigPtr->emit_object_added();
219e1f4db62SRatan Gupta }
220372c5668SAlexander Filippov
221372c5668SAlexander Filippov startOrStopService(phosphor::ldap::nslcdService,
222372c5668SAlexander Filippov ADConfigPtr->enabled() || openLDAPConfigPtr->enabled());
223e1f4db62SRatan Gupta }
224e1f4db62SRatan Gupta
225e1f4db62SRatan Gupta } // namespace ldap
226e1f4db62SRatan Gupta } // namespace phosphor
227