blob: ed40d17eee8cc53eb1d811e0008fda7093e11825 [file] [log] [blame]
Ratan Guptae1f4db62019-04-11 18:57:42 +05301#include "ldap_config_mgr.hpp"
Ratan Gupta37fb3fe2019-04-13 12:54:18 +05302#include "ldap_config.hpp"
Nagaraju Goruganti59287f02018-10-12 07:00:20 -05003#include "utils.hpp"
Ratan Gupta21e88cb2019-04-12 17:15:52 +05304
5#include <cereal/types/string.hpp>
6#include <cereal/types/vector.hpp>
7#include <cereal/archives/binary.hpp>
Ratan Gupta7b04c352019-04-12 21:46:29 +05308#include "ldap_mapper_serialize.hpp"
9
10#include <xyz/openbmc_project/Common/error.hpp>
11#include <xyz/openbmc_project/User/Common/error.hpp>
Ratan Gupta95a29312019-02-18 20:34:10 +053012#include <filesystem>
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -050013#include <fstream>
14#include <sstream>
15
Ratan Gupta21e88cb2019-04-12 17:15:52 +053016// Register class version
17// From cereal documentation;
18// "This macro should be placed at global scope"
19CEREAL_CLASS_VERSION(phosphor::ldap::Config, CLASS_VERSION);
20
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -050021namespace phosphor
22{
23namespace ldap
24{
Ratan Guptae1f4db62019-04-11 18:57:42 +053025
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -050026constexpr auto nslcdService = "nslcd.service";
Nagaraju Gorugantidccee2b2018-09-25 08:51:06 -050027constexpr auto nscdService = "nscd.service";
Nagaraju Goruganti59287f02018-10-12 07:00:20 -050028constexpr auto LDAPscheme = "ldap";
29constexpr auto LDAPSscheme = "ldaps";
Ratan Guptaab4fcb42019-04-29 19:39:51 +053030constexpr auto certObjPath = "/xyz/openbmc_project/certs/client/ldap/1";
31constexpr auto certRootPath = "/xyz/openbmc_project/certs/client/ldap";
32constexpr auto certIface = "xyz.openbmc_project.Certs.Certificate";
33constexpr auto certProperty = "CertificateString";
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -050034
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -050035using namespace phosphor::logging;
36using namespace sdbusplus::xyz::openbmc_project::Common::Error;
Ratan Gupta95a29312019-02-18 20:34:10 +053037namespace fs = std::filesystem;
Ratan Gupta7b04c352019-04-12 21:46:29 +053038
Nagaraju Gorugantib26799a2018-09-28 13:12:19 -050039using Argument = xyz::openbmc_project::Common::InvalidArgument;
Ratan Gupta27d4c012019-04-12 13:03:35 +053040using NotAllowed = sdbusplus::xyz::openbmc_project::Common::Error::NotAllowed;
41using NotAllowedArgument = xyz::openbmc_project::Common::NotAllowed;
Ratan Gupta7b04c352019-04-12 21:46:29 +053042using PrivilegeMappingExists = sdbusplus::xyz::openbmc_project::User::Common::
43 Error::PrivilegeMappingExists;
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -050044
45using Line = std::string;
46using Key = std::string;
47using Val = std::string;
48using ConfigInfo = std::map<Key, Val>;
49
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -050050Config::Config(sdbusplus::bus::bus& bus, const char* path, const char* filePath,
Ratan Gupta22f13f12019-04-29 15:36:40 +053051 const char* caCertFile, const char* certFile, bool secureLDAP,
Nagaraju Goruganti3b4d06a2018-11-08 03:13:38 -060052 std::string lDAPServerURI, std::string lDAPBindDN,
53 std::string lDAPBaseDN, std::string&& lDAPBindDNPassword,
Ratan Guptaaeaf9412019-02-11 04:41:52 -060054 ConfigIface::SearchScope lDAPSearchScope,
55 ConfigIface::Type lDAPType, bool lDAPServiceEnabled,
56 std::string userNameAttr, std::string groupNameAttr,
57 ConfigMgr& parent) :
58 Ifaces(bus, path, true),
Ratan Gupta3a1c2742019-03-20 06:49:42 +053059 secureLDAP(secureLDAP), lDAPBindPassword(std::move(lDAPBindDNPassword)),
Ratan Gupta22f13f12019-04-29 15:36:40 +053060 tlsCacertFile(caCertFile), tlsCertFile(certFile), configFilePath(filePath),
61 objectPath(path), bus(bus), parent(parent),
62 certificateInstalledSignal(
Ratan Guptaab4fcb42019-04-29 19:39:51 +053063 bus, sdbusplus::bus::match::rules::interfacesAdded(certRootPath),
Ratan Gupta22f13f12019-04-29 15:36:40 +053064 std::bind(std::mem_fn(&Config::certificateInstalled), this,
Ratan Guptaab4fcb42019-04-29 19:39:51 +053065 std::placeholders::_1)),
66 certificateChangedSignal(
67 bus,
68 sdbusplus::bus::match::rules::propertiesChanged(certObjPath, certIface),
69 std::bind(std::mem_fn(&Config::certificateChanged), this,
Ratan Gupta22f13f12019-04-29 15:36:40 +053070 std::placeholders::_1))
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -050071{
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -050072 ConfigIface::lDAPServerURI(lDAPServerURI);
73 ConfigIface::lDAPBindDN(lDAPBindDN);
74 ConfigIface::lDAPBaseDN(lDAPBaseDN);
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -050075 ConfigIface::lDAPSearchScope(lDAPSearchScope);
76 ConfigIface::lDAPType(lDAPType);
Ratan Guptaaeaf9412019-02-11 04:41:52 -060077 EnableIface::enabled(lDAPServiceEnabled);
78 ConfigIface::userNameAttribute(userNameAttr);
79 ConfigIface::groupNameAttribute(groupNameAttr);
Ratan Gupta21e88cb2019-04-12 17:15:52 +053080 // NOTE: Don't update the bindDN password under ConfigIface
Ratan Guptaec117542019-04-25 18:38:29 +053081 if (enabled())
82 {
83 writeConfig();
84 }
Ratan Gupta21e88cb2019-04-12 17:15:52 +053085 // save the config.
86 configPersistPath = parent.dbusPersistentPath;
87 configPersistPath += objectPath;
88
89 // create the persistent directory
90 fs::create_directories(configPersistPath);
91
92 configPersistPath += "/config";
93
94 std::ofstream os(configPersistPath, std::ios::binary | std::ios::out);
95 // remove the read permission from others
96 auto permission =
97 fs::perms::owner_read | fs::perms::owner_write | fs::perms::group_read;
98 fs::permissions(configPersistPath, permission);
99
100 serialize();
101
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500102 // Emit deferred signal.
103 this->emit_object_added();
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600104 parent.startOrStopService(nslcdService, enabled());
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500105}
106
Ratan Gupta21e88cb2019-04-12 17:15:52 +0530107Config::Config(sdbusplus::bus::bus& bus, const char* path, const char* filePath,
Ratan Guptaab4fcb42019-04-29 19:39:51 +0530108 const char* caCertFile, const char* certFile,
109 ConfigIface::Type lDAPType, ConfigMgr& parent) :
Ratan Gupta21e88cb2019-04-12 17:15:52 +0530110 Ifaces(bus, path, true),
Ratan Guptaab4fcb42019-04-29 19:39:51 +0530111 tlsCacertFile(caCertFile), tlsCertFile(certFile), configFilePath(filePath),
112 objectPath(path), bus(bus), parent(parent),
Ratan Gupta22f13f12019-04-29 15:36:40 +0530113 certificateInstalledSignal(
Ratan Guptaab4fcb42019-04-29 19:39:51 +0530114 bus, sdbusplus::bus::match::rules::interfacesAdded(certRootPath),
Ratan Gupta22f13f12019-04-29 15:36:40 +0530115 std::bind(std::mem_fn(&Config::certificateInstalled), this,
Ratan Guptaab4fcb42019-04-29 19:39:51 +0530116 std::placeholders::_1)),
117 certificateChangedSignal(
118 bus,
119 sdbusplus::bus::match::rules::propertiesChanged(certObjPath, certIface),
120 std::bind(std::mem_fn(&Config::certificateChanged), this,
Ratan Gupta22f13f12019-04-29 15:36:40 +0530121 std::placeholders::_1))
Ratan Gupta21e88cb2019-04-12 17:15:52 +0530122{
123 ConfigIface::lDAPType(lDAPType);
124
125 configPersistPath = parent.dbusPersistentPath;
126 configPersistPath += objectPath;
127
128 // create the persistent directory
129 fs::create_directories(configPersistPath);
130
131 configPersistPath += "/config";
132
133 std::ofstream os(configPersistPath, std::ios::binary | std::ios::out);
134 // remove the read permission from others
135 auto permission =
136 fs::perms::owner_read | fs::perms::owner_write | fs::perms::group_read;
137 fs::permissions(configPersistPath, permission);
138}
139
Ratan Gupta22f13f12019-04-29 15:36:40 +0530140void Config::certificateInstalled(sdbusplus::message::message& msg)
141{
142 try
143 {
144 if (enabled())
145 {
146 writeConfig();
147 }
148 parent.startOrStopService(nslcdService, enabled());
149 }
150 catch (const InternalFailure& e)
151 {
152 throw;
153 }
154 catch (const std::exception& e)
155 {
156 log<level::ERR>(e.what());
157 elog<InternalFailure>();
158 }
159}
160
Ratan Guptaab4fcb42019-04-29 19:39:51 +0530161void Config::certificateChanged(sdbusplus::message::message& msg)
162{
163 // TODO: Property filtering needs to be done, we need to write
164 // the config only when the property is "Certificate String".
165 try
166 {
167 if (enabled())
168 {
169 writeConfig();
170 }
171 parent.startOrStopService(nslcdService, enabled());
172 }
173 catch (const InternalFailure& e)
174 {
175 throw;
176 }
177 catch (const std::exception& e)
178 {
179 log<level::ERR>(e.what());
180 elog<InternalFailure>();
181 }
182}
183
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500184void Config::writeConfig()
185{
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500186 std::stringstream confData;
Ratan Gupta9891f2f2018-10-06 12:07:35 +0530187 auto isPwdTobeWritten = false;
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600188 std::string userNameAttr;
Ratan Gupta9891f2f2018-10-06 12:07:35 +0530189
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500190 confData << "uid root\n";
191 confData << "gid root\n\n";
192 confData << "ldap_version 3\n\n";
193 confData << "timelimit 30\n";
194 confData << "bind_timelimit 30\n";
195 confData << "pagesize 1000\n";
196 confData << "referrals off\n\n";
197 confData << "uri " << lDAPServerURI() << "\n\n";
198 confData << "base " << lDAPBaseDN() << "\n\n";
199 confData << "binddn " << lDAPBindDN() << "\n";
Ratan Gupta3a1c2742019-03-20 06:49:42 +0530200 if (!lDAPBindPassword.empty())
Nagaraju Goruganti15675472018-10-05 07:03:05 -0500201 {
Ratan Gupta3a1c2742019-03-20 06:49:42 +0530202 confData << "bindpw " << lDAPBindPassword << "\n";
Ratan Gupta9891f2f2018-10-06 12:07:35 +0530203 isPwdTobeWritten = true;
Nagaraju Goruganti15675472018-10-05 07:03:05 -0500204 }
205 confData << "\n";
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500206 switch (lDAPSearchScope())
207 {
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600208 case ConfigIface::SearchScope::sub:
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500209 confData << "scope sub\n\n";
210 break;
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600211 case ConfigIface::SearchScope::one:
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500212 confData << "scope one\n\n";
213 break;
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600214 case ConfigIface::SearchScope::base:
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500215 confData << "scope base\n\n";
216 break;
217 }
218 confData << "base passwd " << lDAPBaseDN() << "\n";
219 confData << "base shadow " << lDAPBaseDN() << "\n\n";
Nagaraju Gorugantidb60f582018-11-08 03:14:48 -0600220 if (secureLDAP == true)
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500221 {
222 confData << "ssl on\n";
Nagaraju Goruganti3b4d06a2018-11-08 03:13:38 -0600223 confData << "tls_reqcert hard\n";
224 confData << "tls_cacertFile " << tlsCacertFile.c_str() << "\n";
Ratan Gupta22f13f12019-04-29 15:36:40 +0530225 if (fs::exists(tlsCertFile.c_str()))
226 {
227 confData << "tls_cert " << tlsCertFile.c_str() << "\n";
228 confData << "tls_key " << tlsCertFile.c_str() << "\n";
229 }
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500230 }
231 else
232 {
Nagaraju Goruganti15675472018-10-05 07:03:05 -0500233 confData << "ssl off\n";
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500234 }
Nagaraju Goruganti15675472018-10-05 07:03:05 -0500235 confData << "\n";
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600236 if (lDAPType() == ConfigIface::Type::ActiveDirectory)
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500237 {
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600238 if (ConfigIface::userNameAttribute().empty())
239 {
240 ConfigIface::userNameAttribute("sAMAccountName");
241 }
242 if (ConfigIface::groupNameAttribute().empty())
243 {
244 ConfigIface::groupNameAttribute("primaryGroupID");
245 }
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500246 confData << "filter passwd (&(objectClass=user)(objectClass=person)"
247 "(!(objectClass=computer)))\n";
248 confData
249 << "filter group (|(objectclass=group)(objectclass=groupofnames) "
250 "(objectclass=groupofuniquenames))\n";
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600251 confData << "map passwd uid "
252 << ConfigIface::userNameAttribute() << "\n";
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500253 confData << "map passwd uidNumber "
254 "objectSid:S-1-5-21-3623811015-3361044348-30300820\n";
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600255 confData << "map passwd gidNumber "
256 << ConfigIface::groupNameAttribute() << "\n";
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500257 confData << "map passwd homeDirectory \"/home/$sAMAccountName\"\n";
258 confData << "map passwd gecos displayName\n";
259 confData << "map passwd loginShell \"/bin/bash\"\n";
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500260 confData << "map group gidNumber "
261 "objectSid:S-1-5-21-3623811015-3361044348-30300820\n";
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600262 confData << "map group cn "
263 << ConfigIface::userNameAttribute() << "\n";
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500264 }
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600265 else if (lDAPType() == ConfigIface::Type::OpenLdap)
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500266 {
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600267 if (ConfigIface::userNameAttribute().empty())
268 {
raviteja-bc3f56c52019-04-02 11:09:04 -0500269 ConfigIface::userNameAttribute("cn");
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600270 }
271 if (ConfigIface::groupNameAttribute().empty())
272 {
raviteja-bc3f56c52019-04-02 11:09:04 -0500273 ConfigIface::groupNameAttribute("gidNumber");
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600274 }
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500275 confData << "filter passwd (objectclass=*)\n";
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500276 confData << "map passwd gecos displayName\n";
Nagaraju Goruganti808eda42018-10-10 08:48:12 -0500277 confData << "filter group (objectclass=posixGroup)\n";
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600278 confData << "map passwd uid "
279 << ConfigIface::userNameAttribute() << "\n";
280 confData << "map passwd gidNumber "
281 << ConfigIface::groupNameAttribute() << "\n";
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500282 }
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500283 try
284 {
285 std::fstream stream(configFilePath.c_str(), std::fstream::out);
Ratan Gupta9891f2f2018-10-06 12:07:35 +0530286 // remove the read permission from others if password is being written.
287 // nslcd forces this behaviour.
288 auto permission = fs::perms::owner_read | fs::perms::owner_write |
289 fs::perms::group_read;
290 if (isPwdTobeWritten)
291 {
292 fs::permissions(configFilePath, permission);
293 }
294 else
295 {
296 fs::permissions(configFilePath,
297 permission | fs::perms::others_read);
298 }
299
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500300 stream << confData.str();
301 stream.flush();
302 stream.close();
303 }
304 catch (const std::exception& e)
305 {
306 log<level::ERR>(e.what());
307 elog<InternalFailure>();
308 }
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500309 return;
310}
311
Ratan Gupta3a1c2742019-03-20 06:49:42 +0530312std::string Config::lDAPBindDNPassword(std::string value)
313{
314 // Don't update the D-bus object, this is just to
315 // facilitate if user wants to change the bind dn password
316 // once d-bus object gets created.
317 lDAPBindPassword = value;
318 try
319 {
Ratan Guptaec117542019-04-25 18:38:29 +0530320 if (enabled())
321 {
322 writeConfig();
323 parent.startOrStopService(nslcdService, enabled());
324 }
Ratan Gupta21e88cb2019-04-12 17:15:52 +0530325 serialize();
Ratan Gupta3a1c2742019-03-20 06:49:42 +0530326 }
327 catch (const InternalFailure& e)
328 {
329 throw;
330 }
331 catch (const std::exception& e)
332 {
333 log<level::ERR>(e.what());
334 elog<InternalFailure>();
335 }
336 return value;
337}
338
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500339std::string Config::lDAPServerURI(std::string value)
340{
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500341 std::string val;
342 try
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500343 {
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500344 if (value == lDAPServerURI())
345 {
346 return value;
347 }
Nagaraju Goruganti59287f02018-10-12 07:00:20 -0500348 if (isValidLDAPURI(value, LDAPSscheme))
Nagaraju Gorugantib26799a2018-09-28 13:12:19 -0500349 {
Nagaraju Goruganti59287f02018-10-12 07:00:20 -0500350 secureLDAP = true;
351 }
352 else if (isValidLDAPURI(value, LDAPscheme))
353 {
354 secureLDAP = false;
Nagaraju Gorugantidb60f582018-11-08 03:14:48 -0600355 }
356 else
357 {
Nagaraju Goruganti59287f02018-10-12 07:00:20 -0500358 log<level::ERR>("bad LDAP Server URI",
359 entry("LDAPSERVERURI=%s", value.c_str()));
360 elog<InvalidArgument>(Argument::ARGUMENT_NAME("lDAPServerURI"),
361 Argument::ARGUMENT_VALUE(value.c_str()));
Nagaraju Gorugantib26799a2018-09-28 13:12:19 -0500362 }
Nagaraju Goruganti3b4d06a2018-11-08 03:13:38 -0600363
364 if (secureLDAP && !fs::exists(tlsCacertFile.c_str()))
365 {
366 log<level::ERR>("LDAP server's CA certificate not provided",
367 entry("TLSCACERTFILE=%s", tlsCacertFile.c_str()));
368 elog<NoCACertificate>();
369 }
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500370 val = ConfigIface::lDAPServerURI(value);
Ratan Guptaec117542019-04-25 18:38:29 +0530371 if (enabled())
372 {
373 writeConfig();
374 parent.startOrStopService(nslcdService, enabled());
375 }
Ratan Gupta21e88cb2019-04-12 17:15:52 +0530376 // save the object.
377 serialize();
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500378 }
379 catch (const InternalFailure& e)
380 {
381 throw;
382 }
Nagaraju Goruganti59287f02018-10-12 07:00:20 -0500383 catch (const InvalidArgument& e)
384 {
385 throw;
386 }
Nagaraju Goruganti3b4d06a2018-11-08 03:13:38 -0600387 catch (const NoCACertificate& e)
388 {
389 throw;
390 }
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500391 catch (const std::exception& e)
392 {
393 log<level::ERR>(e.what());
394 elog<InternalFailure>();
395 }
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500396 return val;
397}
398
399std::string Config::lDAPBindDN(std::string value)
400{
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500401 std::string val;
402 try
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500403 {
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500404 if (value == lDAPBindDN())
405 {
406 return value;
407 }
408
Nagaraju Gorugantib26799a2018-09-28 13:12:19 -0500409 if (value.empty())
410 {
Nagaraju Goruganti59287f02018-10-12 07:00:20 -0500411 log<level::ERR>("Not a valid LDAP BINDDN",
412 entry("LDAPBINDDN=%s", value.c_str()));
Nagaraju Gorugantib26799a2018-09-28 13:12:19 -0500413 elog<InvalidArgument>(Argument::ARGUMENT_NAME("lDAPBindDN"),
414 Argument::ARGUMENT_VALUE(value.c_str()));
415 }
416
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500417 val = ConfigIface::lDAPBindDN(value);
Ratan Guptaec117542019-04-25 18:38:29 +0530418 if (enabled())
419 {
420 writeConfig();
421 parent.startOrStopService(nslcdService, enabled());
422 }
Ratan Gupta21e88cb2019-04-12 17:15:52 +0530423 // save the object.
424 serialize();
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500425 }
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500426 catch (const InternalFailure& e)
427 {
428 throw;
429 }
Nagaraju Gorugantid514e5d2018-11-08 03:07:25 -0600430 catch (const InvalidArgument& e)
431 {
432 throw;
433 }
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500434 catch (const std::exception& e)
435 {
436 log<level::ERR>(e.what());
437 elog<InternalFailure>();
438 }
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500439 return val;
440}
441
442std::string Config::lDAPBaseDN(std::string value)
443{
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500444 std::string val;
445 try
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500446 {
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500447 if (value == lDAPBaseDN())
448 {
449 return value;
450 }
451
Nagaraju Gorugantib26799a2018-09-28 13:12:19 -0500452 if (value.empty())
453 {
Nagaraju Goruganti59287f02018-10-12 07:00:20 -0500454 log<level::ERR>("Not a valid LDAP BASEDN",
455 entry("BASEDN=%s", value.c_str()));
Nagaraju Gorugantib26799a2018-09-28 13:12:19 -0500456 elog<InvalidArgument>(Argument::ARGUMENT_NAME("lDAPBaseDN"),
457 Argument::ARGUMENT_VALUE(value.c_str()));
458 }
459
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500460 val = ConfigIface::lDAPBaseDN(value);
Ratan Guptaec117542019-04-25 18:38:29 +0530461 if (enabled())
462 {
463 writeConfig();
464 parent.startOrStopService(nslcdService, enabled());
465 }
Ratan Gupta21e88cb2019-04-12 17:15:52 +0530466 // save the object.
467 serialize();
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500468 }
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500469 catch (const InternalFailure& e)
470 {
471 throw;
472 }
Nagaraju Gorugantid514e5d2018-11-08 03:07:25 -0600473 catch (const InvalidArgument& e)
474 {
475 throw;
476 }
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500477 catch (const std::exception& e)
478 {
479 log<level::ERR>(e.what());
480 elog<InternalFailure>();
481 }
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500482 return val;
483}
484
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600485ConfigIface::SearchScope Config::lDAPSearchScope(ConfigIface::SearchScope value)
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500486{
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600487 ConfigIface::SearchScope val;
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500488 try
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500489 {
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500490 if (value == lDAPSearchScope())
491 {
492 return value;
493 }
494
495 val = ConfigIface::lDAPSearchScope(value);
Ratan Guptaec117542019-04-25 18:38:29 +0530496 if (enabled())
497 {
498 writeConfig();
499
500 parent.startOrStopService(nslcdService, enabled());
501 }
Ratan Gupta21e88cb2019-04-12 17:15:52 +0530502 // save the object.
503 serialize();
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500504 }
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500505 catch (const InternalFailure& e)
506 {
507 throw;
508 }
509 catch (const std::exception& e)
510 {
511 log<level::ERR>(e.what());
512 elog<InternalFailure>();
513 }
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500514 return val;
515}
516
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600517ConfigIface::Type Config::lDAPType(ConfigIface::Type value)
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500518{
Ratan Gupta27d4c012019-04-12 13:03:35 +0530519 elog<NotAllowed>(NotAllowedArgument::REASON("ReadOnly Property"));
520 return lDAPType();
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500521}
522
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600523bool Config::enabled(bool value)
524{
Ratan Guptac5481d12019-04-12 18:31:05 +0530525 if (value == enabled())
526 {
527 return value;
528 }
529 // Let parent decide that can we enable this config.
530 // It may happen that other config is already enabled,
531 // Current implementation support only one config can
532 // be active at a time.
533 return parent.enableService(*this, value);
534}
535
536bool Config::enableService(bool value)
537{
538 bool isEnable = false;
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600539 try
540 {
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600541 isEnable = EnableIface::enabled(value);
Ratan Guptaec117542019-04-25 18:38:29 +0530542 if (isEnable)
543 {
544 writeConfig();
545 }
Ratan Guptaec117542019-04-25 18:38:29 +0530546 parent.startOrStopService(nslcdService, value);
Ratan Gupta21e88cb2019-04-12 17:15:52 +0530547 serialize();
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600548 }
549 catch (const InternalFailure& e)
550 {
551 throw;
552 }
553 catch (const std::exception& e)
554 {
555 log<level::ERR>(e.what());
556 elog<InternalFailure>();
557 }
558 return isEnable;
559}
560
561std::string Config::userNameAttribute(std::string value)
562{
563 std::string val;
564 try
565 {
566 if (value == userNameAttribute())
567 {
568 return value;
569 }
570
571 val = ConfigIface::userNameAttribute(value);
Ratan Guptaec117542019-04-25 18:38:29 +0530572 if (enabled())
573 {
574 writeConfig();
575
576 parent.startOrStopService(nslcdService, enabled());
577 }
Ratan Gupta21e88cb2019-04-12 17:15:52 +0530578 // save the object.
579 serialize();
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600580 }
581 catch (const InternalFailure& e)
582 {
583 throw;
584 }
585 catch (const std::exception& e)
586 {
587 log<level::ERR>(e.what());
588 elog<InternalFailure>();
589 }
590 return val;
591}
592
593std::string Config::groupNameAttribute(std::string value)
594{
595 std::string val;
596 try
597 {
598 if (value == groupNameAttribute())
599 {
600 return value;
601 }
602
603 val = ConfigIface::groupNameAttribute(value);
Ratan Guptaec117542019-04-25 18:38:29 +0530604 if (enabled())
605 {
606 writeConfig();
607
608 parent.startOrStopService(nslcdService, enabled());
609 }
Ratan Gupta21e88cb2019-04-12 17:15:52 +0530610 // save the object.
611 serialize();
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600612 }
613 catch (const InternalFailure& e)
614 {
615 throw;
616 }
617 catch (const std::exception& e)
618 {
619 log<level::ERR>(e.what());
620 elog<InternalFailure>();
621 }
622 return val;
623}
624
Ratan Gupta21e88cb2019-04-12 17:15:52 +0530625template <class Archive>
626void Config::save(Archive& archive, const std::uint32_t version) const
627{
628 archive(this->enabled());
629 archive(lDAPServerURI());
630 archive(lDAPBindDN());
631 archive(lDAPBaseDN());
632 archive(lDAPSearchScope());
633 archive(lDAPBindPassword);
634 archive(userNameAttribute());
635 archive(groupNameAttribute());
636}
637
638template <class Archive>
639void Config::load(Archive& archive, const std::uint32_t version)
640{
641
642 bool bVal;
643 archive(bVal);
644 EnableIface::enabled(bVal);
645
646 std::string str;
647 archive(str);
648 ConfigIface::lDAPServerURI(str);
649
650 archive(str);
651 ConfigIface::lDAPBindDN(str);
652
653 archive(str);
654 ConfigIface::lDAPBaseDN(str);
655
656 ConfigIface::SearchScope scope;
657 archive(scope);
658 ConfigIface::lDAPSearchScope(scope);
659
660 archive(str);
661 lDAPBindPassword = str;
662
663 archive(str);
664 ConfigIface::userNameAttribute(str);
665
666 archive(str);
667 ConfigIface::groupNameAttribute(str);
668}
669
670void Config::serialize()
671{
672 std::ofstream os(configPersistPath.string(),
673 std::ios::binary | std::ios::out);
674 cereal::BinaryOutputArchive oarchive(os);
675 oarchive(*this);
676 return;
677}
678
679bool Config::deserialize()
680{
681 try
682 {
683 if (fs::exists(configPersistPath))
684 {
685 std::ifstream is(configPersistPath.c_str(),
686 std::ios::in | std::ios::binary);
687 cereal::BinaryInputArchive iarchive(is);
688 iarchive(*this);
689 return true;
690 }
691 return false;
692 }
693 catch (cereal::Exception& e)
694 {
695 log<level::ERR>(e.what());
696 std::error_code ec;
697 fs::remove(configPersistPath, ec);
698 return false;
699 }
700 catch (const fs::filesystem_error& e)
701 {
702 return false;
703 }
704}
705
Ratan Gupta7b04c352019-04-12 21:46:29 +0530706ObjectPath Config::create(std::string groupName, std::string privilege)
707{
708 checkPrivilegeMapper(groupName);
709 checkPrivilegeLevel(privilege);
710
711 entryId++;
712
713 // Object path for the LDAP group privilege mapper entry
714 fs::path mapperObjectPath = objectPath;
715 mapperObjectPath /= "role_map";
716 mapperObjectPath /= std::to_string(entryId);
717
718 fs::path persistPath = parent.dbusPersistentPath;
719 persistPath += mapperObjectPath;
720
721 // Create mapping for LDAP privilege mapper entry
722 auto entry = std::make_unique<LDAPMapperEntry>(
723 bus, mapperObjectPath.string().c_str(), persistPath.string().c_str(),
724 groupName, privilege, *this);
725
726 phosphor::ldap::serialize(*entry, std::move(persistPath));
727
728 PrivilegeMapperList.emplace(entryId, std::move(entry));
729 return mapperObjectPath.string();
730}
731
732void Config::deletePrivilegeMapper(Id id)
733{
734 fs::path mapperObjectPath = objectPath;
735 mapperObjectPath /= "role_map";
736 mapperObjectPath /= std::to_string(id);
737
738 fs::path persistPath = parent.dbusPersistentPath;
739 persistPath += std::move(mapperObjectPath);
740
741 // Delete the persistent representation of the privilege mapper.
742 fs::remove(std::move(persistPath));
743
744 PrivilegeMapperList.erase(id);
745}
746void Config::checkPrivilegeMapper(const std::string& groupName)
747{
748 if (groupName.empty())
749 {
750 log<level::ERR>("Group name is empty");
751 elog<InvalidArgument>(Argument::ARGUMENT_NAME("Group name"),
752 Argument::ARGUMENT_VALUE("Null"));
753 }
754
755 for (const auto& val : PrivilegeMapperList)
756 {
757 if (val.second.get()->groupName() == groupName)
758 {
759 log<level::ERR>("Group name already exists");
760 elog<PrivilegeMappingExists>();
761 }
762 }
763}
764
765void Config::checkPrivilegeLevel(const std::string& privilege)
766{
767 if (privilege.empty())
768 {
769 log<level::ERR>("Privilege level is empty");
770 elog<InvalidArgument>(Argument::ARGUMENT_NAME("Privilege level"),
771 Argument::ARGUMENT_VALUE("Null"));
772 }
773
774 if (std::find(privMgr.begin(), privMgr.end(), privilege) == privMgr.end())
775 {
776 log<level::ERR>("Invalid privilege");
777 elog<InvalidArgument>(Argument::ARGUMENT_NAME("Privilege level"),
778 Argument::ARGUMENT_VALUE(privilege.c_str()));
779 }
780}
781
782void Config::restoreRoleMapping()
783{
784 namespace fs = std::filesystem;
785 fs::path dir = parent.dbusPersistentPath;
786 dir += objectPath;
787 dir /= "role_map";
788
789 if (!fs::exists(dir) || fs::is_empty(dir))
790 {
791 return;
792 }
793
794 for (auto& file : fs::directory_iterator(dir))
795 {
796 std::string id = file.path().filename().c_str();
797 size_t idNum = std::stol(id);
798
799 auto entryPath = objectPath + '/' + "role_map" + '/' + id;
800 auto persistPath = parent.dbusPersistentPath + entryPath;
801 auto entry = std::make_unique<LDAPMapperEntry>(
802 bus, entryPath.c_str(), persistPath.c_str(), *this);
803 if (phosphor::ldap::deserialize(file.path(), *entry))
804 {
805 entry->Interfaces::emit_object_added();
806 PrivilegeMapperList.emplace(idNum, std::move(entry));
807 if (idNum > entryId)
808 {
809 entryId = idNum;
810 }
811 }
812 }
813}
814
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500815} // namespace ldap
816} // namespace phosphor