blob: a3592736cc06e20be7a3f78e81806e1204f90b0e [file] [log] [blame]
Ratan Guptae1f4db62019-04-11 18:57:42 +05301#include "ldap_config_mgr.hpp"
Ratan Guptae1f4db62019-04-11 18:57:42 +05302
Patrick Williams9638afb2021-02-22 17:16:24 -06003#include "ldap_config.hpp"
Ratan Guptae1f4db62019-04-11 18:57:42 +05304#include "utils.hpp"
Patrick Williams9638afb2021-02-22 17:16:24 -06005
Ratan Guptae1f4db62019-04-11 18:57:42 +05306#include <filesystem>
7#include <fstream>
8#include <sstream>
9
10namespace phosphor
11{
12namespace ldap
13{
14
Alexander Filippov372c5662021-06-30 20:23:39 +030015constexpr auto nslcdService = "nslcd.service";
Ratan Guptae1f4db62019-04-11 18:57:42 +053016constexpr auto nscdService = "nscd.service";
Nan Zhou78d85042022-08-29 17:50:22 +000017constexpr auto ldapScheme = "ldap";
18constexpr auto ldapsScheme = "ldaps";
Ratan Guptae1f4db62019-04-11 18:57:42 +053019
20using namespace phosphor::logging;
21using namespace sdbusplus::xyz::openbmc_project::Common::Error;
22namespace fs = std::filesystem;
23using Argument = xyz::openbmc_project::Common::InvalidArgument;
Ratan Guptac5481d12019-04-12 18:31:05 +053024using NotAllowed = sdbusplus::xyz::openbmc_project::Common::Error::NotAllowed;
25using NotAllowedArgument = xyz::openbmc_project::Common::NotAllowed;
Ratan Guptae1f4db62019-04-11 18:57:42 +053026
27using Line = std::string;
28using Key = std::string;
29using Val = std::string;
30using ConfigInfo = std::map<Key, Val>;
31
32void ConfigMgr::startOrStopService(const std::string& service, bool start)
33{
34 if (start)
35 {
36 restartService(service);
37 }
38 else
39 {
40 stopService(service);
41 }
42}
43
44void ConfigMgr::restartService(const std::string& service)
45{
46 try
47 {
48 auto method = bus.new_method_call(SYSTEMD_BUSNAME, SYSTEMD_PATH,
49 SYSTEMD_INTERFACE, "RestartUnit");
50 method.append(service.c_str(), "replace");
51 bus.call_noreply(method);
52 }
Patrick Williamsb3ef4e12022-07-22 19:26:55 -050053 catch (const sdbusplus::exception_t& ex)
Ratan Guptae1f4db62019-04-11 18:57:42 +053054 {
55 log<level::ERR>("Failed to restart service",
56 entry("SERVICE=%s", service.c_str()),
57 entry("ERR=%s", ex.what()));
58 elog<InternalFailure>();
59 }
60}
61void ConfigMgr::stopService(const std::string& service)
62{
63 try
64 {
65 auto method = bus.new_method_call(SYSTEMD_BUSNAME, SYSTEMD_PATH,
66 SYSTEMD_INTERFACE, "StopUnit");
67 method.append(service.c_str(), "replace");
68 bus.call_noreply(method);
69 }
Patrick Williamsb3ef4e12022-07-22 19:26:55 -050070 catch (const sdbusplus::exception_t& ex)
Ratan Guptae1f4db62019-04-11 18:57:42 +053071 {
72 log<level::ERR>("Failed to stop service",
73 entry("SERVICE=%s", service.c_str()),
74 entry("ERR=%s", ex.what()));
75 elog<InternalFailure>();
76 }
77}
78
Ratan Guptae1f4db62019-04-11 18:57:42 +053079std::string ConfigMgr::createConfig(
Patrick Williamse6500a42021-05-01 05:58:23 -050080 std::string ldapServerURI, std::string ldapBindDN, std::string ldapBaseDN,
81 std::string ldapBindDNPassword, CreateIface::SearchScope ldapSearchScope,
82 CreateIface::Create::Type ldapType, std::string groupNameAttribute,
Ratan Guptae1f4db62019-04-11 18:57:42 +053083 std::string userNameAttribute)
84{
85 bool secureLDAP = false;
86
Nan Zhou78d85042022-08-29 17:50:22 +000087 if (isValidLDAPURI(ldapServerURI, ldapsScheme))
Ratan Guptae1f4db62019-04-11 18:57:42 +053088 {
89 secureLDAP = true;
90 }
Nan Zhou78d85042022-08-29 17:50:22 +000091 else if (isValidLDAPURI(ldapServerURI, ldapScheme))
Ratan Guptae1f4db62019-04-11 18:57:42 +053092 {
93 secureLDAP = false;
94 }
95 else
96 {
97 log<level::ERR>("bad LDAP Server URI",
Patrick Williamse6500a42021-05-01 05:58:23 -050098 entry("LDAPSERVERURI=%s", ldapServerURI.c_str()));
99 elog<InvalidArgument>(Argument::ARGUMENT_NAME("ldapServerURI"),
100 Argument::ARGUMENT_VALUE(ldapServerURI.c_str()));
Ratan Guptae1f4db62019-04-11 18:57:42 +0530101 }
102
103 if (secureLDAP && !fs::exists(tlsCacertFile.c_str()))
104 {
105 log<level::ERR>("LDAP server's CA certificate not provided",
106 entry("TLSCACERTFILE=%s", tlsCacertFile.c_str()));
107 elog<NoCACertificate>();
108 }
109
Patrick Williamse6500a42021-05-01 05:58:23 -0500110 if (ldapBindDN.empty())
Ratan Guptae1f4db62019-04-11 18:57:42 +0530111 {
112 log<level::ERR>("Not a valid LDAP BINDDN",
Patrick Williamse6500a42021-05-01 05:58:23 -0500113 entry("LDAPBINDDN=%s", ldapBindDN.c_str()));
Ratan Guptae1f4db62019-04-11 18:57:42 +0530114 elog<InvalidArgument>(Argument::ARGUMENT_NAME("LDAPBindDN"),
Patrick Williamse6500a42021-05-01 05:58:23 -0500115 Argument::ARGUMENT_VALUE(ldapBindDN.c_str()));
Ratan Guptae1f4db62019-04-11 18:57:42 +0530116 }
117
Patrick Williamse6500a42021-05-01 05:58:23 -0500118 if (ldapBaseDN.empty())
Ratan Guptae1f4db62019-04-11 18:57:42 +0530119 {
120 log<level::ERR>("Not a valid LDAP BASEDN",
Patrick Williamse6500a42021-05-01 05:58:23 -0500121 entry("LDAPBASEDN=%s", ldapBaseDN.c_str()));
Ratan Guptae1f4db62019-04-11 18:57:42 +0530122 elog<InvalidArgument>(Argument::ARGUMENT_NAME("LDAPBaseDN"),
Patrick Williamse6500a42021-05-01 05:58:23 -0500123 Argument::ARGUMENT_VALUE(ldapBaseDN.c_str()));
Ratan Guptae1f4db62019-04-11 18:57:42 +0530124 }
125
Ratan Gupta27d4c012019-04-12 13:03:35 +0530126 // With current implementation we support only two default LDAP server.
127 // which will be always there but when the support comes for additional
128 // account providers then the create config would be used to create the
129 // additional config.
Ratan Guptae1f4db62019-04-11 18:57:42 +0530130
Ratan Gupta27d4c012019-04-12 13:03:35 +0530131 std::string objPath;
Ratan Guptae1f4db62019-04-11 18:57:42 +0530132
Patrick Williamse6500a42021-05-01 05:58:23 -0500133 if (static_cast<ConfigIface::Type>(ldapType) == ConfigIface::Type::OpenLdap)
Ratan Gupta27d4c012019-04-12 13:03:35 +0530134 {
135 openLDAPConfigPtr.reset(nullptr);
136 objPath = openLDAPDbusObjectPath;
137 openLDAPConfigPtr = std::make_unique<Config>(
138 bus, objPath.c_str(), configFilePath.c_str(), tlsCacertFile.c_str(),
Patrick Williamse6500a42021-05-01 05:58:23 -0500139 tlsCertFile.c_str(), secureLDAP, ldapServerURI, ldapBindDN,
140 ldapBaseDN, std::move(ldapBindDNPassword),
141 static_cast<ConfigIface::SearchScope>(ldapSearchScope),
142 static_cast<ConfigIface::Type>(ldapType), false, groupNameAttribute,
Ratan Gupta27d4c012019-04-12 13:03:35 +0530143 userNameAttribute, *this);
144 }
145 else
146 {
147 ADConfigPtr.reset(nullptr);
Nan Zhou78d85042022-08-29 17:50:22 +0000148 objPath = adDbusObjectPath;
Ratan Gupta27d4c012019-04-12 13:03:35 +0530149 ADConfigPtr = std::make_unique<Config>(
150 bus, objPath.c_str(), configFilePath.c_str(), tlsCacertFile.c_str(),
Patrick Williamse6500a42021-05-01 05:58:23 -0500151 tlsCertFile.c_str(), secureLDAP, ldapServerURI, ldapBindDN,
152 ldapBaseDN, std::move(ldapBindDNPassword),
153 static_cast<ConfigIface::SearchScope>(ldapSearchScope),
154 static_cast<ConfigIface::Type>(ldapType), false, groupNameAttribute,
Ratan Gupta27d4c012019-04-12 13:03:35 +0530155 userNameAttribute, *this);
156 }
Ratan Guptae1f4db62019-04-11 18:57:42 +0530157 restartService(nscdService);
158 return objPath;
159}
160
Ratan Gupta27d4c012019-04-12 13:03:35 +0530161void ConfigMgr::createDefaultObjects()
Ratan Guptae1f4db62019-04-11 18:57:42 +0530162{
Ratan Gupta27d4c012019-04-12 13:03:35 +0530163 if (!openLDAPConfigPtr)
Ratan Guptae1f4db62019-04-11 18:57:42 +0530164 {
Ratan Gupta27d4c012019-04-12 13:03:35 +0530165 openLDAPConfigPtr = std::make_unique<Config>(
166 bus, openLDAPDbusObjectPath.c_str(), configFilePath.c_str(),
Ratan Guptaab4fcb42019-04-29 19:39:51 +0530167 tlsCacertFile.c_str(), tlsCertFile.c_str(),
168 ConfigIface::Type::OpenLdap, *this);
Ratan Gupta21e88cb2019-04-12 17:15:52 +0530169 openLDAPConfigPtr->emit_object_added();
Ratan Guptae1f4db62019-04-11 18:57:42 +0530170 }
Ratan Gupta27d4c012019-04-12 13:03:35 +0530171 if (!ADConfigPtr)
Ratan Guptae1f4db62019-04-11 18:57:42 +0530172 {
Ratan Gupta27d4c012019-04-12 13:03:35 +0530173 ADConfigPtr = std::make_unique<Config>(
Nan Zhou78d85042022-08-29 17:50:22 +0000174 bus, adDbusObjectPath.c_str(), configFilePath.c_str(),
Ratan Guptaab4fcb42019-04-29 19:39:51 +0530175 tlsCacertFile.c_str(), tlsCertFile.c_str(),
176 ConfigIface::Type::ActiveDirectory, *this);
Ratan Gupta21e88cb2019-04-12 17:15:52 +0530177 ADConfigPtr->emit_object_added();
178 }
179}
180
Ratan Guptac5481d12019-04-12 18:31:05 +0530181bool ConfigMgr::enableService(Config& config, bool value)
182{
183 if (value)
184 {
185 if (openLDAPConfigPtr && openLDAPConfigPtr->enabled())
186 {
187 elog<NotAllowed>(NotAllowedArgument::REASON(
188 "OpenLDAP service is already active"));
189 }
190 if (ADConfigPtr && ADConfigPtr->enabled())
191 {
192 elog<NotAllowed>(NotAllowedArgument::REASON(
193 "ActiveDirectory service is already active"));
194 }
195 }
196 return config.enableService(value);
197}
198
Ratan Gupta21e88cb2019-04-12 17:15:52 +0530199void ConfigMgr::restore()
200{
201 createDefaultObjects();
202 // Restore the ldap config and their mappings
203 if (ADConfigPtr->deserialize())
204 {
Ratan Gupta7b04c352019-04-12 21:46:29 +0530205 // Restore the role mappings
206 ADConfigPtr->restoreRoleMapping();
Ratan Gupta21e88cb2019-04-12 17:15:52 +0530207 ADConfigPtr->emit_object_added();
208 }
209 if (openLDAPConfigPtr->deserialize())
210 {
Ratan Gupta7b04c352019-04-12 21:46:29 +0530211 // Restore the role mappings
212 openLDAPConfigPtr->restoreRoleMapping();
Ratan Gupta21e88cb2019-04-12 17:15:52 +0530213 openLDAPConfigPtr->emit_object_added();
Ratan Guptae1f4db62019-04-11 18:57:42 +0530214 }
Alexander Filippov372c5662021-06-30 20:23:39 +0300215
216 startOrStopService(phosphor::ldap::nslcdService,
217 ADConfigPtr->enabled() || openLDAPConfigPtr->enabled());
Ratan Guptae1f4db62019-04-11 18:57:42 +0530218}
Ratan Gupta27d4c012019-04-12 13:03:35 +0530219
Ratan Guptae1f4db62019-04-11 18:57:42 +0530220} // namespace ldap
221} // namespace phosphor