1e1f4db62SRatan Gupta #include "ldap_config_mgr.hpp"
237fb3feeSRatan Gupta #include "ldap_config.hpp"
3e1f4db62SRatan Gupta 
4e1f4db62SRatan Gupta #include "utils.hpp"
5e1f4db62SRatan Gupta #include <filesystem>
6e1f4db62SRatan Gupta #include <fstream>
7e1f4db62SRatan Gupta #include <sstream>
8e1f4db62SRatan Gupta 
9e1f4db62SRatan Gupta namespace phosphor
10e1f4db62SRatan Gupta {
11e1f4db62SRatan Gupta namespace ldap
12e1f4db62SRatan Gupta {
13e1f4db62SRatan Gupta 
14e1f4db62SRatan Gupta constexpr auto nscdService = "nscd.service";
15e1f4db62SRatan Gupta constexpr auto LDAPscheme = "ldap";
16e1f4db62SRatan Gupta constexpr auto LDAPSscheme = "ldaps";
17e1f4db62SRatan Gupta 
18e1f4db62SRatan Gupta using namespace phosphor::logging;
19e1f4db62SRatan Gupta using namespace sdbusplus::xyz::openbmc_project::Common::Error;
20e1f4db62SRatan Gupta namespace fs = std::filesystem;
21e1f4db62SRatan Gupta using Argument = xyz::openbmc_project::Common::InvalidArgument;
22*c5481d1cSRatan Gupta using NotAllowed = sdbusplus::xyz::openbmc_project::Common::Error::NotAllowed;
23*c5481d1cSRatan Gupta using NotAllowedArgument = xyz::openbmc_project::Common::NotAllowed;
24e1f4db62SRatan Gupta 
25e1f4db62SRatan Gupta using Line = std::string;
26e1f4db62SRatan Gupta using Key = std::string;
27e1f4db62SRatan Gupta using Val = std::string;
28e1f4db62SRatan Gupta using ConfigInfo = std::map<Key, Val>;
29e1f4db62SRatan Gupta 
30e1f4db62SRatan Gupta void ConfigMgr::startOrStopService(const std::string& service, bool start)
31e1f4db62SRatan Gupta {
32e1f4db62SRatan Gupta     if (start)
33e1f4db62SRatan Gupta     {
34e1f4db62SRatan Gupta         restartService(service);
35e1f4db62SRatan Gupta     }
36e1f4db62SRatan Gupta     else
37e1f4db62SRatan Gupta     {
38e1f4db62SRatan Gupta         stopService(service);
39e1f4db62SRatan Gupta     }
40e1f4db62SRatan Gupta }
41e1f4db62SRatan Gupta 
42e1f4db62SRatan Gupta void ConfigMgr::restartService(const std::string& service)
43e1f4db62SRatan Gupta {
44e1f4db62SRatan Gupta     try
45e1f4db62SRatan Gupta     {
46e1f4db62SRatan Gupta         auto method = bus.new_method_call(SYSTEMD_BUSNAME, SYSTEMD_PATH,
47e1f4db62SRatan Gupta                                           SYSTEMD_INTERFACE, "RestartUnit");
48e1f4db62SRatan Gupta         method.append(service.c_str(), "replace");
49e1f4db62SRatan Gupta         bus.call_noreply(method);
50e1f4db62SRatan Gupta     }
51e1f4db62SRatan Gupta     catch (const sdbusplus::exception::SdBusError& ex)
52e1f4db62SRatan Gupta     {
53e1f4db62SRatan Gupta         log<level::ERR>("Failed to restart service",
54e1f4db62SRatan Gupta                         entry("SERVICE=%s", service.c_str()),
55e1f4db62SRatan Gupta                         entry("ERR=%s", ex.what()));
56e1f4db62SRatan Gupta         elog<InternalFailure>();
57e1f4db62SRatan Gupta     }
58e1f4db62SRatan Gupta }
59e1f4db62SRatan Gupta void ConfigMgr::stopService(const std::string& service)
60e1f4db62SRatan Gupta {
61e1f4db62SRatan Gupta     try
62e1f4db62SRatan Gupta     {
63e1f4db62SRatan Gupta         auto method = bus.new_method_call(SYSTEMD_BUSNAME, SYSTEMD_PATH,
64e1f4db62SRatan Gupta                                           SYSTEMD_INTERFACE, "StopUnit");
65e1f4db62SRatan Gupta         method.append(service.c_str(), "replace");
66e1f4db62SRatan Gupta         bus.call_noreply(method);
67e1f4db62SRatan Gupta     }
68e1f4db62SRatan Gupta     catch (const sdbusplus::exception::SdBusError& ex)
69e1f4db62SRatan Gupta     {
70e1f4db62SRatan Gupta         log<level::ERR>("Failed to stop service",
71e1f4db62SRatan Gupta                         entry("SERVICE=%s", service.c_str()),
72e1f4db62SRatan Gupta                         entry("ERR=%s", ex.what()));
73e1f4db62SRatan Gupta         elog<InternalFailure>();
74e1f4db62SRatan Gupta     }
75e1f4db62SRatan Gupta }
76e1f4db62SRatan Gupta 
77e1f4db62SRatan Gupta std::string ConfigMgr::createConfig(
78e1f4db62SRatan Gupta     std::string lDAPServerURI, std::string lDAPBindDN, std::string lDAPBaseDN,
79e1f4db62SRatan Gupta     std::string lDAPBindDNPassword, CreateIface::SearchScope lDAPSearchScope,
80e1f4db62SRatan Gupta     CreateIface::Create::Type lDAPType, std::string groupNameAttribute,
81e1f4db62SRatan Gupta     std::string userNameAttribute)
82e1f4db62SRatan Gupta {
83e1f4db62SRatan Gupta     bool secureLDAP = false;
84e1f4db62SRatan Gupta 
85e1f4db62SRatan Gupta     if (isValidLDAPURI(lDAPServerURI, LDAPSscheme))
86e1f4db62SRatan Gupta     {
87e1f4db62SRatan Gupta         secureLDAP = true;
88e1f4db62SRatan Gupta     }
89e1f4db62SRatan Gupta     else if (isValidLDAPURI(lDAPServerURI, LDAPscheme))
90e1f4db62SRatan Gupta     {
91e1f4db62SRatan Gupta         secureLDAP = false;
92e1f4db62SRatan Gupta     }
93e1f4db62SRatan Gupta     else
94e1f4db62SRatan Gupta     {
95e1f4db62SRatan Gupta         log<level::ERR>("bad LDAP Server URI",
96e1f4db62SRatan Gupta                         entry("LDAPSERVERURI=%s", lDAPServerURI.c_str()));
97e1f4db62SRatan Gupta         elog<InvalidArgument>(Argument::ARGUMENT_NAME("lDAPServerURI"),
98e1f4db62SRatan Gupta                               Argument::ARGUMENT_VALUE(lDAPServerURI.c_str()));
99e1f4db62SRatan Gupta     }
100e1f4db62SRatan Gupta 
101e1f4db62SRatan Gupta     if (secureLDAP && !fs::exists(tlsCacertFile.c_str()))
102e1f4db62SRatan Gupta     {
103e1f4db62SRatan Gupta         log<level::ERR>("LDAP server's CA certificate not provided",
104e1f4db62SRatan Gupta                         entry("TLSCACERTFILE=%s", tlsCacertFile.c_str()));
105e1f4db62SRatan Gupta         elog<NoCACertificate>();
106e1f4db62SRatan Gupta     }
107e1f4db62SRatan Gupta 
108e1f4db62SRatan Gupta     if (lDAPBindDN.empty())
109e1f4db62SRatan Gupta     {
110e1f4db62SRatan Gupta         log<level::ERR>("Not a valid LDAP BINDDN",
111e1f4db62SRatan Gupta                         entry("LDAPBINDDN=%s", lDAPBindDN.c_str()));
112e1f4db62SRatan Gupta         elog<InvalidArgument>(Argument::ARGUMENT_NAME("LDAPBindDN"),
113e1f4db62SRatan Gupta                               Argument::ARGUMENT_VALUE(lDAPBindDN.c_str()));
114e1f4db62SRatan Gupta     }
115e1f4db62SRatan Gupta 
116e1f4db62SRatan Gupta     if (lDAPBaseDN.empty())
117e1f4db62SRatan Gupta     {
118e1f4db62SRatan Gupta         log<level::ERR>("Not a valid LDAP BASEDN",
119e1f4db62SRatan Gupta                         entry("LDAPBASEDN=%s", lDAPBaseDN.c_str()));
120e1f4db62SRatan Gupta         elog<InvalidArgument>(Argument::ARGUMENT_NAME("LDAPBaseDN"),
121e1f4db62SRatan Gupta                               Argument::ARGUMENT_VALUE(lDAPBaseDN.c_str()));
122e1f4db62SRatan Gupta     }
123e1f4db62SRatan Gupta 
12427d4c011SRatan Gupta     // With current implementation we support only two default LDAP server.
12527d4c011SRatan Gupta     // which will be always there but when the support comes for additional
12627d4c011SRatan Gupta     // account providers then the create config would be used to create the
12727d4c011SRatan Gupta     // additional config.
128e1f4db62SRatan Gupta 
12927d4c011SRatan Gupta     std::string objPath;
13027d4c011SRatan Gupta 
13127d4c011SRatan Gupta     if (static_cast<ConfigIface::Type>(lDAPType) == ConfigIface::Type::OpenLdap)
13227d4c011SRatan Gupta     {
13327d4c011SRatan Gupta         openLDAPConfigPtr.reset(nullptr);
13427d4c011SRatan Gupta         objPath = openLDAPDbusObjectPath;
13527d4c011SRatan Gupta         openLDAPConfigPtr = std::make_unique<Config>(
136e1f4db62SRatan Gupta             bus, objPath.c_str(), configFilePath.c_str(), tlsCacertFile.c_str(),
137e1f4db62SRatan Gupta             secureLDAP, lDAPServerURI, lDAPBindDN, lDAPBaseDN,
138e1f4db62SRatan Gupta             std::move(lDAPBindDNPassword),
139e1f4db62SRatan Gupta             static_cast<ConfigIface::SearchScope>(lDAPSearchScope),
140e1f4db62SRatan Gupta             static_cast<ConfigIface::Type>(lDAPType), false, groupNameAttribute,
141e1f4db62SRatan Gupta             userNameAttribute, *this);
14227d4c011SRatan Gupta     }
14327d4c011SRatan Gupta     else
14427d4c011SRatan Gupta     {
14527d4c011SRatan Gupta         ADConfigPtr.reset(nullptr);
14627d4c011SRatan Gupta         objPath = ADDbusObjectPath;
14727d4c011SRatan Gupta         ADConfigPtr = std::make_unique<Config>(
14827d4c011SRatan Gupta             bus, objPath.c_str(), configFilePath.c_str(), tlsCacertFile.c_str(),
14927d4c011SRatan Gupta             secureLDAP, lDAPServerURI, lDAPBindDN, lDAPBaseDN,
15027d4c011SRatan Gupta             std::move(lDAPBindDNPassword),
15127d4c011SRatan Gupta             static_cast<ConfigIface::SearchScope>(lDAPSearchScope),
15227d4c011SRatan Gupta             static_cast<ConfigIface::Type>(lDAPType), false, groupNameAttribute,
15327d4c011SRatan Gupta             userNameAttribute, *this);
15427d4c011SRatan Gupta     }
155e1f4db62SRatan Gupta     restartService(nscdService);
156e1f4db62SRatan Gupta     return objPath;
157e1f4db62SRatan Gupta }
158e1f4db62SRatan Gupta 
15927d4c011SRatan Gupta void ConfigMgr::createDefaultObjects()
160e1f4db62SRatan Gupta {
16127d4c011SRatan Gupta     if (!openLDAPConfigPtr)
162e1f4db62SRatan Gupta     {
16327d4c011SRatan Gupta         openLDAPConfigPtr = std::make_unique<Config>(
16427d4c011SRatan Gupta             bus, openLDAPDbusObjectPath.c_str(), configFilePath.c_str(),
16521e88cb5SRatan Gupta             tlsCacertFile.c_str(), ConfigIface::Type::OpenLdap, *this);
16621e88cb5SRatan Gupta         openLDAPConfigPtr->emit_object_added();
167e1f4db62SRatan Gupta     }
16827d4c011SRatan Gupta     if (!ADConfigPtr)
169e1f4db62SRatan Gupta     {
17027d4c011SRatan Gupta         ADConfigPtr = std::make_unique<Config>(
17127d4c011SRatan Gupta             bus, ADDbusObjectPath.c_str(), configFilePath.c_str(),
17221e88cb5SRatan Gupta             tlsCacertFile.c_str(), ConfigIface::Type::ActiveDirectory, *this);
17321e88cb5SRatan Gupta         ADConfigPtr->emit_object_added();
17421e88cb5SRatan Gupta     }
17521e88cb5SRatan Gupta }
17621e88cb5SRatan Gupta 
177*c5481d1cSRatan Gupta bool ConfigMgr::enableService(Config& config, bool value)
178*c5481d1cSRatan Gupta {
179*c5481d1cSRatan Gupta     if (value)
180*c5481d1cSRatan Gupta     {
181*c5481d1cSRatan Gupta         if (openLDAPConfigPtr && openLDAPConfigPtr->enabled())
182*c5481d1cSRatan Gupta         {
183*c5481d1cSRatan Gupta             elog<NotAllowed>(NotAllowedArgument::REASON(
184*c5481d1cSRatan Gupta                 "OpenLDAP service is already active"));
185*c5481d1cSRatan Gupta         }
186*c5481d1cSRatan Gupta         if (ADConfigPtr && ADConfigPtr->enabled())
187*c5481d1cSRatan Gupta         {
188*c5481d1cSRatan Gupta             elog<NotAllowed>(NotAllowedArgument::REASON(
189*c5481d1cSRatan Gupta                 "ActiveDirectory service is already active"));
190*c5481d1cSRatan Gupta         }
191*c5481d1cSRatan Gupta     }
192*c5481d1cSRatan Gupta     return config.enableService(value);
193*c5481d1cSRatan Gupta }
194*c5481d1cSRatan Gupta 
19521e88cb5SRatan Gupta void ConfigMgr::restore()
19621e88cb5SRatan Gupta {
19721e88cb5SRatan Gupta     createDefaultObjects();
19821e88cb5SRatan Gupta     // Restore the ldap config and their mappings
19921e88cb5SRatan Gupta     if (ADConfigPtr->deserialize())
20021e88cb5SRatan Gupta     {
20121e88cb5SRatan Gupta         // Restore the role mappings in later commit
20221e88cb5SRatan Gupta         ADConfigPtr->emit_object_added();
20321e88cb5SRatan Gupta     }
20421e88cb5SRatan Gupta     if (openLDAPConfigPtr->deserialize())
20521e88cb5SRatan Gupta     {
20621e88cb5SRatan Gupta         // Restore the role mappings in later commit
20721e88cb5SRatan Gupta         openLDAPConfigPtr->emit_object_added();
208e1f4db62SRatan Gupta     }
209e1f4db62SRatan Gupta }
210e1f4db62SRatan Gupta 
211e1f4db62SRatan Gupta } // namespace ldap
212e1f4db62SRatan Gupta } // namespace phosphor
213