1 #include "ldap_config.hpp"
2
3 #include "ldap_config_mgr.hpp"
4 #include "ldap_mapper_serialize.hpp"
5 #include "utils.hpp"
6
7 #include <cereal/archives/binary.hpp>
8 #include <cereal/types/string.hpp>
9 #include <cereal/types/vector.hpp>
10 #include <phosphor-logging/elog-errors.hpp>
11 #include <phosphor-logging/elog.hpp>
12 #include <phosphor-logging/lg2.hpp>
13 #include <xyz/openbmc_project/Common/error.hpp>
14 #include <xyz/openbmc_project/User/Common/error.hpp>
15
16 #include <filesystem>
17 #include <fstream>
18 #include <sstream>
19
20 // Register class version
21 // From cereal documentation;
22 // "This macro should be placed at global scope"
23 CEREAL_CLASS_VERSION(phosphor::ldap::Config, CLASS_VERSION);
24
25 namespace phosphor
26 {
27 namespace ldap
28 {
29
30 constexpr auto nslcdService = "nslcd.service";
31 constexpr auto ldapScheme = "ldap";
32 constexpr auto ldapsScheme = "ldaps";
33 constexpr auto certObjPath = "/xyz/openbmc_project/certs/client/ldap/1";
34 constexpr auto certRootPath = "/xyz/openbmc_project/certs/client/ldap";
35 constexpr auto authObjPath = "/xyz/openbmc_project/certs/authority/truststore";
36 constexpr auto certIface = "xyz.openbmc_project.Certs.Certificate";
37 constexpr auto certProperty = "CertificateString";
38
39 using namespace phosphor::logging;
40 using namespace sdbusplus::xyz::openbmc_project::Common::Error;
41 namespace fs = std::filesystem;
42
43 using Argument = xyz::openbmc_project::Common::InvalidArgument;
44 using NotAllowedArgument = xyz::openbmc_project::Common::NotAllowed;
45 using PrivilegeMappingExists = sdbusplus::xyz::openbmc_project::User::Common::
46 Error::PrivilegeMappingExists;
47
48 using Line = std::string;
49 using Key = std::string;
50 using Val = std::string;
51 using ConfigInfo = std::map<Key, Val>;
52
Config(sdbusplus::bus_t & bus,const char * path,const char * filePath,const char * caCertFile,const char * certFile,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)53 Config::Config(sdbusplus::bus_t& bus, const char* path, const char* filePath,
54 const char* caCertFile, const char* certFile, bool secureLDAP,
55 std::string ldapServerURI, std::string ldapBindDN,
56 std::string ldapBaseDN, std::string&& ldapBindDNPassword,
57 ConfigIface::SearchScope ldapSearchScope,
58 ConfigIface::Type ldapType, bool ldapServiceEnabled,
59 std::string userNameAttr, std::string groupNameAttr,
60 ConfigMgr& parent) :
61 Ifaces(bus, path, Ifaces::action::defer_emit),
62 secureLDAP(secureLDAP), ldapBindPassword(std::move(ldapBindDNPassword)),
63 tlsCacertFile(caCertFile), tlsCertFile(certFile), configFilePath(filePath),
64 objectPath(path), bus(bus), parent(parent),
65 certificateInstalledSignal(
66 bus, sdbusplus::bus::match::rules::interfacesAdded(certRootPath),
67 std::bind(std::mem_fn(&Config::certificateInstalled), this,
68 std::placeholders::_1)),
69
70 cacertificateInstalledSignal(
71 bus, sdbusplus::bus::match::rules::interfacesAdded(authObjPath),
72 std::bind(std::mem_fn(&Config::certificateInstalled), this,
73 std::placeholders::_1)),
74
75 certificateChangedSignal(
76 bus,
77 sdbusplus::bus::match::rules::propertiesChanged(certObjPath, certIface),
78 std::bind(std::mem_fn(&Config::certificateChanged), this,
79 std::placeholders::_1))
80 {
81 ConfigIface::ldapServerURI(ldapServerURI);
82 ConfigIface::ldapBindDN(ldapBindDN);
83 ConfigIface::ldapBaseDN(ldapBaseDN);
84 ConfigIface::ldapSearchScope(ldapSearchScope);
85 ConfigIface::ldapType(ldapType);
86 EnableIface::enabled(ldapServiceEnabled);
87 ConfigIface::userNameAttribute(userNameAttr);
88 ConfigIface::groupNameAttribute(groupNameAttr);
89 // NOTE: Don't update the bindDN password under ConfigIface
90 if (enabled())
91 {
92 writeConfig();
93 }
94 // save the config.
95 configPersistPath = parent.dbusPersistentPath;
96 configPersistPath += objectPath;
97
98 // create the persistent directory
99 fs::create_directories(configPersistPath);
100
101 configPersistPath += "/config";
102
103 serialize();
104
105 // Emit deferred signal.
106 this->emit_object_added();
107 parent.startOrStopService(nslcdService, enabled());
108 }
109
Config(sdbusplus::bus_t & bus,const char * path,const char * filePath,const char * caCertFile,const char * certFile,ConfigIface::Type ldapType,ConfigMgr & parent)110 Config::Config(sdbusplus::bus_t& bus, const char* path, const char* filePath,
111 const char* caCertFile, const char* certFile,
112 ConfigIface::Type ldapType, ConfigMgr& parent) :
113 Ifaces(bus, path, Ifaces::action::defer_emit),
114 secureLDAP(false), tlsCacertFile(caCertFile), tlsCertFile(certFile),
115 configFilePath(filePath), objectPath(path), bus(bus), parent(parent),
116 certificateInstalledSignal(
117 bus, sdbusplus::bus::match::rules::interfacesAdded(certRootPath),
118 std::bind(std::mem_fn(&Config::certificateInstalled), this,
119 std::placeholders::_1)),
120 cacertificateInstalledSignal(
121 bus, sdbusplus::bus::match::rules::interfacesAdded(authObjPath),
122 std::bind(std::mem_fn(&Config::certificateInstalled), this,
123 std::placeholders::_1)),
124 certificateChangedSignal(
125 bus,
126 sdbusplus::bus::match::rules::propertiesChanged(certObjPath, certIface),
127 std::bind(std::mem_fn(&Config::certificateChanged), this,
128 std::placeholders::_1))
129 {
130 ConfigIface::ldapType(ldapType);
131
132 configPersistPath = parent.dbusPersistentPath;
133 configPersistPath += objectPath;
134
135 // create the persistent directory
136 fs::create_directories(configPersistPath);
137
138 configPersistPath += "/config";
139 }
140
certificateInstalled(sdbusplus::message_t &)141 void Config::certificateInstalled(sdbusplus::message_t& /*msg*/)
142 {
143 try
144 {
145 if (enabled())
146 {
147 writeConfig();
148 }
149 parent.startOrStopService(nslcdService, enabled());
150 }
151 catch (const InternalFailure& e)
152 {
153 throw;
154 }
155 catch (const std::exception& e)
156 {
157 lg2::error("Exception: {ERR}", "ERR", e);
158 elog<InternalFailure>();
159 }
160 }
161
certificateChanged(sdbusplus::message_t & msg)162 void Config::certificateChanged(sdbusplus::message_t& msg)
163 {
164 std::string objectName;
165 std::map<std::string, std::variant<std::string>> msgData;
166 msg.read(objectName, msgData);
167 auto valPropMap = msgData.find(certProperty);
168 {
169 if (valPropMap != msgData.end())
170 {
171 try
172 {
173 if (enabled())
174 {
175 writeConfig();
176 }
177 parent.startOrStopService(nslcdService, enabled());
178 }
179 catch (const InternalFailure& e)
180 {
181 throw;
182 }
183 catch (const std::exception& e)
184 {
185 lg2::error("Exception: {ERR}", "ERR", e);
186 elog<InternalFailure>();
187 }
188 }
189 }
190 }
191
writeConfig()192 void Config::writeConfig()
193 {
194 std::stringstream confData;
195 auto isPwdTobeWritten = false;
196 std::string userNameAttr;
197
198 confData << "uid root\n";
199 confData << "gid root\n\n";
200 confData << "ldap_version 3\n\n";
201 confData << "timelimit 30\n";
202 confData << "bind_timelimit 30\n";
203 confData << "pagesize 1000\n";
204 confData << "referrals off\n\n";
205 confData << "uri " << ldapServerURI() << "\n\n";
206 confData << "base " << ldapBaseDN() << "\n\n";
207 confData << "binddn " << ldapBindDN() << "\n";
208 if (!ldapBindPassword.empty())
209 {
210 confData << "bindpw " << ldapBindPassword << "\n";
211 isPwdTobeWritten = true;
212 }
213 confData << "\n";
214 switch (ldapSearchScope())
215 {
216 case ConfigIface::SearchScope::sub:
217 confData << "scope sub\n\n";
218 break;
219 case ConfigIface::SearchScope::one:
220 confData << "scope one\n\n";
221 break;
222 case ConfigIface::SearchScope::base:
223 confData << "scope base\n\n";
224 break;
225 }
226 confData << "base passwd " << ldapBaseDN() << "\n";
227 confData << "base shadow " << ldapBaseDN() << "\n\n";
228 if (secureLDAP == true)
229 {
230 confData << "ssl on\n";
231 confData << "tls_reqcert hard\n";
232 if (fs::is_directory(tlsCacertFile.c_str()))
233 {
234 confData << "tls_cacertdir " << tlsCacertFile.c_str() << "\n";
235 }
236 else
237 {
238 confData << "tls_cacertfile " << tlsCacertFile.c_str() << "\n";
239 }
240 if (fs::exists(tlsCertFile.c_str()))
241 {
242 confData << "tls_cert " << tlsCertFile.c_str() << "\n";
243 confData << "tls_key " << tlsCertFile.c_str() << "\n";
244 }
245 }
246 else
247 {
248 confData << "ssl off\n";
249 }
250 confData << "\n";
251 if (ldapType() == ConfigIface::Type::ActiveDirectory)
252 {
253 if (ConfigIface::userNameAttribute().empty())
254 {
255 ConfigIface::userNameAttribute("sAMAccountName");
256 }
257 if (ConfigIface::groupNameAttribute().empty())
258 {
259 ConfigIface::groupNameAttribute("primaryGroupID");
260 }
261 confData << "filter passwd (&(objectClass=user)(objectClass=person)"
262 "(!(objectClass=computer)))\n";
263 confData
264 << "filter group (|(objectclass=group)(objectclass=groupofnames) "
265 "(objectclass=groupofuniquenames))\n";
266 confData << "map passwd uid "
267 << ConfigIface::userNameAttribute() << "\n";
268 confData << "map passwd uidNumber "
269 "objectSid:S-1-5-21-3623811015-3361044348-30300820\n";
270 confData << "map passwd gidNumber "
271 << ConfigIface::groupNameAttribute() << "\n";
272 confData << "map passwd homeDirectory \"/home/$sAMAccountName\"\n";
273 confData << "map passwd gecos displayName\n";
274 confData << "map passwd loginShell \"/bin/sh\"\n";
275 confData << "map group gidNumber "
276 "objectSid:S-1-5-21-3623811015-3361044348-30300820\n";
277 confData << "map group cn "
278 << ConfigIface::userNameAttribute() << "\n";
279 confData << "nss_initgroups_ignoreusers ALLLOCAL\n";
280 }
281 else if (ldapType() == ConfigIface::Type::OpenLdap)
282 {
283 if (ConfigIface::userNameAttribute().empty())
284 {
285 ConfigIface::userNameAttribute("cn");
286 }
287 if (ConfigIface::groupNameAttribute().empty())
288 {
289 ConfigIface::groupNameAttribute("gidNumber");
290 }
291 confData << "filter passwd (objectclass=*)\n";
292 confData << "map passwd gecos displayName\n";
293 confData << "filter group (objectclass=posixGroup)\n";
294 confData << "map passwd uid "
295 << ConfigIface::userNameAttribute() << "\n";
296 confData << "map passwd gidNumber "
297 << ConfigIface::groupNameAttribute() << "\n";
298 confData << "map passwd loginShell \"/bin/sh\"\n";
299 confData << "nss_initgroups_ignoreusers ALLLOCAL\n";
300 }
301 try
302 {
303 std::fstream stream(configFilePath.c_str(), std::fstream::out);
304 // remove the read permission from others if password is being written.
305 // nslcd forces this behaviour.
306 auto permission = fs::perms::owner_read | fs::perms::owner_write |
307 fs::perms::group_read;
308 if (isPwdTobeWritten)
309 {
310 fs::permissions(configFilePath, permission);
311 }
312 else
313 {
314 fs::permissions(configFilePath,
315 permission | fs::perms::others_read);
316 }
317
318 stream << confData.str();
319 stream.flush();
320 stream.close();
321 }
322 catch (const std::exception& e)
323 {
324 lg2::error("Exception: {ERR}", "ERR", e);
325 elog<InternalFailure>();
326 }
327 return;
328 }
329
ldapBindDNPassword(std::string value)330 std::string Config::ldapBindDNPassword(std::string value)
331 {
332 // Don't update the D-bus object, this is just to
333 // facilitate if user wants to change the bind dn password
334 // once d-bus object gets created.
335 ldapBindPassword = value;
336 try
337 {
338 if (enabled())
339 {
340 writeConfig();
341 parent.startOrStopService(nslcdService, enabled());
342 }
343 serialize();
344 }
345 catch (const InternalFailure& e)
346 {
347 throw;
348 }
349 catch (const std::exception& e)
350 {
351 lg2::error("Exception: {ERR}", "ERR", e);
352 elog<InternalFailure>();
353 }
354 return value;
355 }
356
ldapServerURI(std::string value)357 std::string Config::ldapServerURI(std::string value)
358 {
359 std::string val;
360 try
361 {
362 if (value == ldapServerURI())
363 {
364 return value;
365 }
366 if (isValidLDAPURI(value, ldapsScheme))
367 {
368 secureLDAP = true;
369 }
370 else if (isValidLDAPURI(value, ldapScheme))
371 {
372 secureLDAP = false;
373 }
374 else
375 {
376 lg2::error("Bad LDAP Server URI {URI}", "URI", value);
377 elog<InvalidArgument>(Argument::ARGUMENT_NAME("ldapServerURI"),
378 Argument::ARGUMENT_VALUE(value.c_str()));
379 }
380
381 if (secureLDAP && !fs::exists(tlsCacertFile.c_str()))
382 {
383 lg2::error("LDAP server CA certificate not found at {PATH}", "PATH",
384 tlsCacertFile);
385 elog<NoCACertificate>();
386 }
387 val = ConfigIface::ldapServerURI(value);
388 if (enabled())
389 {
390 writeConfig();
391 parent.startOrStopService(nslcdService, enabled());
392 }
393 // save the object.
394 serialize();
395 }
396 catch (const InternalFailure& e)
397 {
398 throw;
399 }
400 catch (const InvalidArgument& e)
401 {
402 throw;
403 }
404 catch (const NoCACertificate& e)
405 {
406 throw;
407 }
408 catch (const std::exception& e)
409 {
410 lg2::error("Exception: {ERR}", "ERR", e);
411 elog<InternalFailure>();
412 }
413 return val;
414 }
415
ldapBindDN(std::string value)416 std::string Config::ldapBindDN(std::string value)
417 {
418 std::string val;
419 try
420 {
421 if (value == ldapBindDN())
422 {
423 return value;
424 }
425
426 if (value.empty())
427 {
428 lg2::error("'{BINDDN}' is not a valid LDAP BindDN", "BINDDN",
429 value);
430 elog<InvalidArgument>(Argument::ARGUMENT_NAME("ldapBindDN"),
431 Argument::ARGUMENT_VALUE(value.c_str()));
432 }
433
434 val = ConfigIface::ldapBindDN(value);
435 if (enabled())
436 {
437 writeConfig();
438 parent.startOrStopService(nslcdService, enabled());
439 }
440 // save the object.
441 serialize();
442 }
443 catch (const InternalFailure& e)
444 {
445 throw;
446 }
447 catch (const InvalidArgument& e)
448 {
449 throw;
450 }
451 catch (const std::exception& e)
452 {
453 lg2::error("Exception: {ERR}", "ERR", e);
454 elog<InternalFailure>();
455 }
456 return val;
457 }
458
ldapBaseDN(std::string value)459 std::string Config::ldapBaseDN(std::string value)
460 {
461 std::string val;
462 try
463 {
464 if (value == ldapBaseDN())
465 {
466 return value;
467 }
468
469 if (value.empty())
470 {
471 lg2::error("'{BASEDN}' is not a valid LDAP BaseDN", "BASEDN",
472 value);
473 elog<InvalidArgument>(Argument::ARGUMENT_NAME("ldapBaseDN"),
474 Argument::ARGUMENT_VALUE(value.c_str()));
475 }
476
477 val = ConfigIface::ldapBaseDN(value);
478 if (enabled())
479 {
480 writeConfig();
481 parent.startOrStopService(nslcdService, enabled());
482 }
483 // save the object.
484 serialize();
485 }
486 catch (const InternalFailure& e)
487 {
488 throw;
489 }
490 catch (const InvalidArgument& e)
491 {
492 throw;
493 }
494 catch (const std::exception& e)
495 {
496 lg2::error("Exception: {ERR}", "ERR", e);
497 elog<InternalFailure>();
498 }
499 return val;
500 }
501
ldapSearchScope(ConfigIface::SearchScope value)502 ConfigIface::SearchScope Config::ldapSearchScope(ConfigIface::SearchScope value)
503 {
504 ConfigIface::SearchScope val;
505 try
506 {
507 if (value == ldapSearchScope())
508 {
509 return value;
510 }
511
512 val = ConfigIface::ldapSearchScope(value);
513 if (enabled())
514 {
515 writeConfig();
516
517 parent.startOrStopService(nslcdService, enabled());
518 }
519 // save the object.
520 serialize();
521 }
522 catch (const InternalFailure& e)
523 {
524 throw;
525 }
526 catch (const std::exception& e)
527 {
528 lg2::error("Exception: {ERR}", "ERR", e);
529 elog<InternalFailure>();
530 }
531 return val;
532 }
533
ldapType(ConfigIface::Type)534 ConfigIface::Type Config::ldapType(ConfigIface::Type /*value*/)
535 {
536 elog<NotAllowed>(NotAllowedArgument::REASON("ReadOnly Property"));
537 return ldapType();
538 }
539
enabled(bool value)540 bool Config::enabled(bool value)
541 {
542 if (value == enabled())
543 {
544 return value;
545 }
546 // Let parent decide that can we enable this config.
547 // It may happen that other config is already enabled,
548 // Current implementation support only one config can
549 // be active at a time.
550 return parent.enableService(*this, value);
551 }
552
enableService(bool value)553 bool Config::enableService(bool value)
554 {
555 bool isEnable = false;
556 try
557 {
558 isEnable = EnableIface::enabled(value);
559 if (isEnable)
560 {
561 writeConfig();
562 }
563 parent.startOrStopService(nslcdService, value);
564 serialize();
565 }
566 catch (const InternalFailure& e)
567 {
568 throw;
569 }
570 catch (const std::exception& e)
571 {
572 lg2::error("Exception: {ERR}", "ERR", e);
573 elog<InternalFailure>();
574 }
575 return isEnable;
576 }
577
userNameAttribute(std::string value)578 std::string Config::userNameAttribute(std::string value)
579 {
580 std::string val;
581 try
582 {
583 if (value == userNameAttribute())
584 {
585 return value;
586 }
587
588 val = ConfigIface::userNameAttribute(value);
589 if (enabled())
590 {
591 writeConfig();
592
593 parent.startOrStopService(nslcdService, enabled());
594 }
595 // save the object.
596 serialize();
597 }
598 catch (const InternalFailure& e)
599 {
600 throw;
601 }
602 catch (const std::exception& e)
603 {
604 lg2::error("Exception: {ERR}", "ERR", e);
605 elog<InternalFailure>();
606 }
607 return val;
608 }
609
groupNameAttribute(std::string value)610 std::string Config::groupNameAttribute(std::string value)
611 {
612 std::string val;
613 try
614 {
615 if (value == groupNameAttribute())
616 {
617 return value;
618 }
619
620 val = ConfigIface::groupNameAttribute(value);
621 if (enabled())
622 {
623 writeConfig();
624
625 parent.startOrStopService(nslcdService, enabled());
626 }
627 // save the object.
628 serialize();
629 }
630 catch (const InternalFailure& e)
631 {
632 throw;
633 }
634 catch (const std::exception& e)
635 {
636 lg2::error("Exception: {ERR}", "ERR", e);
637 elog<InternalFailure>();
638 }
639 return val;
640 }
641
642 template <class Archive>
save(Archive & archive,const std::uint32_t) const643 void Config::save(Archive& archive, const std::uint32_t /*version*/) const
644 {
645 archive(this->enabled());
646 archive(ldapServerURI());
647 archive(ldapBindDN());
648 archive(ldapBaseDN());
649 archive(ldapSearchScope());
650 archive(ldapBindPassword);
651 archive(userNameAttribute());
652 archive(groupNameAttribute());
653 }
654
655 template <class Archive>
load(Archive & archive,const std::uint32_t)656 void Config::load(Archive& archive, const std::uint32_t /*version*/)
657 {
658 bool bVal;
659 archive(bVal);
660 EnableIface::enabled(bVal);
661
662 std::string str;
663 archive(str);
664 ConfigIface::ldapServerURI(str);
665
666 archive(str);
667 ConfigIface::ldapBindDN(str);
668
669 archive(str);
670 ConfigIface::ldapBaseDN(str);
671
672 ConfigIface::SearchScope scope;
673 archive(scope);
674 ConfigIface::ldapSearchScope(scope);
675
676 archive(str);
677 ldapBindPassword = str;
678
679 archive(str);
680 ConfigIface::userNameAttribute(str);
681
682 archive(str);
683 ConfigIface::groupNameAttribute(str);
684 }
685
serialize()686 void Config::serialize()
687 {
688 if (!fs::exists(configPersistPath.c_str()))
689 {
690 std::ofstream os(configPersistPath.string(),
691 std::ios::binary | std::ios::out);
692 auto permission = fs::perms::owner_read | fs::perms::owner_write |
693 fs::perms::group_read;
694 fs::permissions(configPersistPath, permission);
695 cereal::BinaryOutputArchive oarchive(os);
696 oarchive(*this);
697 }
698 else
699 {
700 std::ofstream os(configPersistPath.string(),
701 std::ios::binary | std::ios::out);
702 cereal::BinaryOutputArchive oarchive(os);
703 oarchive(*this);
704 }
705 return;
706 }
707
deserialize()708 bool Config::deserialize()
709 {
710 try
711 {
712 if (fs::exists(configPersistPath))
713 {
714 std::ifstream is(configPersistPath.c_str(),
715 std::ios::in | std::ios::binary);
716 cereal::BinaryInputArchive iarchive(is);
717 iarchive(*this);
718
719 if (isValidLDAPURI(ldapServerURI(), ldapScheme))
720 {
721 secureLDAP = false;
722 }
723 else if (isValidLDAPURI(ldapServerURI(), ldapsScheme))
724 {
725 secureLDAP = true;
726 }
727 return true;
728 }
729 return false;
730 }
731 catch (const cereal::Exception& e)
732 {
733 lg2::error("Exception: {ERR}", "ERR", e);
734 std::error_code ec;
735 fs::remove(configPersistPath, ec);
736 return false;
737 }
738 catch (const fs::filesystem_error& e)
739 {
740 return false;
741 }
742 }
743
create(std::string groupName,std::string privilege)744 ObjectPath Config::create(std::string groupName, std::string privilege)
745 {
746 checkPrivilegeMapper(groupName);
747 checkPrivilegeLevel(privilege);
748
749 entryId++;
750
751 // Object path for the LDAP group privilege mapper entry
752 fs::path mapperObjectPath = objectPath;
753 mapperObjectPath /= "role_map";
754 mapperObjectPath /= std::to_string(entryId);
755
756 fs::path persistPath = parent.dbusPersistentPath;
757 persistPath += mapperObjectPath;
758
759 // Create mapping for LDAP privilege mapper entry
760 auto entry = std::make_unique<LDAPMapperEntry>(
761 bus, mapperObjectPath.string().c_str(), persistPath.string().c_str(),
762 groupName, privilege, *this);
763
764 phosphor::ldap::serialize(*entry, std::move(persistPath));
765
766 PrivilegeMapperList.emplace(entryId, std::move(entry));
767 return mapperObjectPath.string();
768 }
769
deletePrivilegeMapper(Id id)770 void Config::deletePrivilegeMapper(Id id)
771 {
772 fs::path mapperObjectPath = objectPath;
773 mapperObjectPath /= "role_map";
774 mapperObjectPath /= std::to_string(id);
775
776 fs::path persistPath = parent.dbusPersistentPath;
777 persistPath += std::move(mapperObjectPath);
778
779 // Delete the persistent representation of the privilege mapper.
780 fs::remove(std::move(persistPath));
781
782 PrivilegeMapperList.erase(id);
783 }
checkPrivilegeMapper(const std::string & groupName)784 void Config::checkPrivilegeMapper(const std::string& groupName)
785 {
786 if (groupName.empty())
787 {
788 lg2::error("Group name is empty");
789 elog<InvalidArgument>(Argument::ARGUMENT_NAME("Group name"),
790 Argument::ARGUMENT_VALUE("Null"));
791 }
792
793 for (const auto& val : PrivilegeMapperList)
794 {
795 if (val.second.get()->groupName() == groupName)
796 {
797 lg2::error("Group name '{GROUPNAME}' already exists", "GROUPNAME",
798 groupName);
799 elog<PrivilegeMappingExists>();
800 }
801 }
802 }
803
checkPrivilegeLevel(const std::string & privilege)804 void Config::checkPrivilegeLevel(const std::string& privilege)
805 {
806 if (privilege.empty())
807 {
808 lg2::error("Privilege level is empty");
809 elog<InvalidArgument>(Argument::ARGUMENT_NAME("Privilege level"),
810 Argument::ARGUMENT_VALUE("Null"));
811 }
812
813 if (std::find(privMgr.begin(), privMgr.end(), privilege) == privMgr.end())
814 {
815 lg2::error("Invalid privilege '{PRIVILEGE}'", "PRIVILEGE", privilege);
816 elog<InvalidArgument>(Argument::ARGUMENT_NAME("Privilege"),
817 Argument::ARGUMENT_VALUE(privilege.c_str()));
818 }
819 }
820
restoreRoleMapping()821 void Config::restoreRoleMapping()
822 {
823 namespace fs = std::filesystem;
824 fs::path dir = parent.dbusPersistentPath;
825 dir += objectPath;
826 dir /= "role_map";
827
828 if (!fs::exists(dir) || fs::is_empty(dir))
829 {
830 return;
831 }
832
833 for (auto& file : fs::directory_iterator(dir))
834 {
835 std::string id = file.path().filename().c_str();
836 size_t idNum = std::stol(id);
837
838 auto entryPath = objectPath + '/' + "role_map" + '/' + id;
839 auto persistPath = parent.dbusPersistentPath + entryPath;
840 auto entry = std::make_unique<LDAPMapperEntry>(
841 bus, entryPath.c_str(), persistPath.c_str(), *this);
842 if (phosphor::ldap::deserialize(file.path(), *entry))
843 {
844 entry->Interfaces::emit_object_added();
845 PrivilegeMapperList.emplace(idNum, std::move(entry));
846 if (idNum > entryId)
847 {
848 entryId = idNum;
849 }
850 }
851 }
852 }
853
854 } // namespace ldap
855 } // namespace phosphor
856