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