xref: /openbmc/phosphor-user-manager/phosphor-ldap-config/ldap_config.cpp (revision 0b1ad3d8cbf0ef3d95494603d351de0ed3463647)
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 <xyz/openbmc_project/Common/error.hpp>
11 #include <xyz/openbmc_project/User/Common/error.hpp>
12 
13 #include <filesystem>
14 #include <fstream>
15 #include <sstream>
16 
17 // Register class version
18 // From cereal documentation;
19 // "This macro should be placed at global scope"
20 CEREAL_CLASS_VERSION(phosphor::ldap::Config, CLASS_VERSION);
21 
22 namespace phosphor
23 {
24 namespace ldap
25 {
26 
27 constexpr auto nslcdService = "nslcd.service";
28 constexpr auto nscdService = "nscd.service";
29 constexpr auto LDAPscheme = "ldap";
30 constexpr auto LDAPSscheme = "ldaps";
31 constexpr auto certObjPath = "/xyz/openbmc_project/certs/client/ldap/1";
32 constexpr auto certRootPath = "/xyz/openbmc_project/certs/client/ldap";
33 constexpr auto authObjPath = "/xyz/openbmc_project/certs/authority/ldap";
34 constexpr auto certIface = "xyz.openbmc_project.Certs.Certificate";
35 constexpr auto certProperty = "CertificateString";
36 
37 using namespace phosphor::logging;
38 using namespace sdbusplus::xyz::openbmc_project::Common::Error;
39 namespace fs = std::filesystem;
40 
41 using Argument = xyz::openbmc_project::Common::InvalidArgument;
42 using NotAllowed = sdbusplus::xyz::openbmc_project::Common::Error::NotAllowed;
43 using NotAllowedArgument = xyz::openbmc_project::Common::NotAllowed;
44 using PrivilegeMappingExists = sdbusplus::xyz::openbmc_project::User::Common::
45     Error::PrivilegeMappingExists;
46 
47 using Line = std::string;
48 using Key = std::string;
49 using Val = std::string;
50 using ConfigInfo = std::map<Key, Val>;
51 
52 Config::Config(sdbusplus::bus::bus& bus, const char* path, const char* filePath,
53                const char* caCertFile, const char* certFile, bool secureLDAP,
54                std::string ldapServerURI, std::string ldapBindDN,
55                std::string ldapBaseDN, std::string&& ldapBindDNPassword,
56                ConfigIface::SearchScope ldapSearchScope,
57                ConfigIface::Type ldapType, bool ldapServiceEnabled,
58                std::string userNameAttr, std::string groupNameAttr,
59                ConfigMgr& parent) :
60     Ifaces(bus, path, true),
61     secureLDAP(secureLDAP), ldapBindPassword(std::move(ldapBindDNPassword)),
62     tlsCacertFile(caCertFile), tlsCertFile(certFile), configFilePath(filePath),
63     objectPath(path), bus(bus), 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 
109 Config::Config(sdbusplus::bus::bus& bus, const char* path, const char* filePath,
110                const char* caCertFile, const char* certFile,
111                ConfigIface::Type ldapType, ConfigMgr& parent) :
112     Ifaces(bus, path, true),
113     secureLDAP(false), tlsCacertFile(caCertFile), tlsCertFile(certFile),
114     configFilePath(filePath), 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 
140 void 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 
161 void Config::certificateChanged(sdbusplus::message::message& 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 
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                 log<level::ERR>(e.what());
186                 elog<InternalFailure>();
187             }
188         }
189     }
190 }
191 
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/bash\"\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 << "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         log<level::ERR>(e.what());
324         elog<InternalFailure>();
325     }
326     return;
327 }
328 
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         log<level::ERR>(e.what());
351         elog<InternalFailure>();
352     }
353     return value;
354 }
355 
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             log<level::ERR>("bad LDAP Server URI",
376                             entry("LDAPSERVERURI=%s", value.c_str()));
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             log<level::ERR>("LDAP server's CA certificate not provided",
384                             entry("TLSCACERTFILE=%s", tlsCacertFile.c_str()));
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         log<level::ERR>(e.what());
411         elog<InternalFailure>();
412     }
413     return val;
414 }
415 
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             log<level::ERR>("Not a valid LDAP BINDDN",
429                             entry("LDAPBINDDN=%s", value.c_str()));
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         log<level::ERR>(e.what());
454         elog<InternalFailure>();
455     }
456     return val;
457 }
458 
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             log<level::ERR>("Not a valid LDAP BASEDN",
472                             entry("BASEDN=%s", value.c_str()));
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         log<level::ERR>(e.what());
497         elog<InternalFailure>();
498     }
499     return val;
500 }
501 
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         log<level::ERR>(e.what());
529         elog<InternalFailure>();
530     }
531     return val;
532 }
533 
534 ConfigIface::Type Config::ldapType(ConfigIface::Type /*value*/)
535 {
536     elog<NotAllowed>(NotAllowedArgument::REASON("ReadOnly Property"));
537     return ldapType();
538 }
539 
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 
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         log<level::ERR>(e.what());
573         elog<InternalFailure>();
574     }
575     return isEnable;
576 }
577 
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         log<level::ERR>(e.what());
605         elog<InternalFailure>();
606     }
607     return val;
608 }
609 
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         log<level::ERR>(e.what());
637         elog<InternalFailure>();
638     }
639     return val;
640 }
641 
642 template <class Archive>
643 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>
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 
686 void Config::serialize()
687 {
688 
689     if (!fs::exists(configPersistPath.c_str()))
690     {
691         std::ofstream os(configPersistPath.string(),
692                          std::ios::binary | std::ios::out);
693         auto permission = fs::perms::owner_read | fs::perms::owner_write |
694                           fs::perms::group_read;
695         fs::permissions(configPersistPath, permission);
696         cereal::BinaryOutputArchive oarchive(os);
697         oarchive(*this);
698     }
699     else
700     {
701         std::ofstream os(configPersistPath.string(),
702                          std::ios::binary | std::ios::out);
703         cereal::BinaryOutputArchive oarchive(os);
704         oarchive(*this);
705     }
706     return;
707 }
708 
709 bool Config::deserialize()
710 {
711     try
712     {
713         if (fs::exists(configPersistPath))
714         {
715             std::ifstream is(configPersistPath.c_str(),
716                              std::ios::in | std::ios::binary);
717             cereal::BinaryInputArchive iarchive(is);
718             iarchive(*this);
719 
720             if (isValidLDAPURI(ldapServerURI(), LDAPscheme))
721             {
722                 secureLDAP = false;
723             }
724             else if (isValidLDAPURI(ldapServerURI(), LDAPSscheme))
725             {
726                 secureLDAP = true;
727             }
728             return true;
729         }
730         return false;
731     }
732     catch (const cereal::Exception& e)
733     {
734         log<level::ERR>(e.what());
735         std::error_code ec;
736         fs::remove(configPersistPath, ec);
737         return false;
738     }
739     catch (const fs::filesystem_error& e)
740     {
741         return false;
742     }
743 }
744 
745 ObjectPath Config::create(std::string groupName, std::string privilege)
746 {
747     checkPrivilegeMapper(groupName);
748     checkPrivilegeLevel(privilege);
749 
750     entryId++;
751 
752     // Object path for the LDAP group privilege mapper entry
753     fs::path mapperObjectPath = objectPath;
754     mapperObjectPath /= "role_map";
755     mapperObjectPath /= std::to_string(entryId);
756 
757     fs::path persistPath = parent.dbusPersistentPath;
758     persistPath += mapperObjectPath;
759 
760     // Create mapping for LDAP privilege mapper entry
761     auto entry = std::make_unique<LDAPMapperEntry>(
762         bus, mapperObjectPath.string().c_str(), persistPath.string().c_str(),
763         groupName, privilege, *this);
764 
765     phosphor::ldap::serialize(*entry, std::move(persistPath));
766 
767     PrivilegeMapperList.emplace(entryId, std::move(entry));
768     return mapperObjectPath.string();
769 }
770 
771 void Config::deletePrivilegeMapper(Id id)
772 {
773     fs::path mapperObjectPath = objectPath;
774     mapperObjectPath /= "role_map";
775     mapperObjectPath /= std::to_string(id);
776 
777     fs::path persistPath = parent.dbusPersistentPath;
778     persistPath += std::move(mapperObjectPath);
779 
780     // Delete the persistent representation of the privilege mapper.
781     fs::remove(std::move(persistPath));
782 
783     PrivilegeMapperList.erase(id);
784 }
785 void Config::checkPrivilegeMapper(const std::string& groupName)
786 {
787     if (groupName.empty())
788     {
789         log<level::ERR>("Group name is empty");
790         elog<InvalidArgument>(Argument::ARGUMENT_NAME("Group name"),
791                               Argument::ARGUMENT_VALUE("Null"));
792     }
793 
794     for (const auto& val : PrivilegeMapperList)
795     {
796         if (val.second.get()->groupName() == groupName)
797         {
798             log<level::ERR>("Group name already exists");
799             elog<PrivilegeMappingExists>();
800         }
801     }
802 }
803 
804 void Config::checkPrivilegeLevel(const std::string& privilege)
805 {
806     if (privilege.empty())
807     {
808         log<level::ERR>("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         log<level::ERR>("Invalid privilege");
816         elog<InvalidArgument>(Argument::ARGUMENT_NAME("Privilege level"),
817                               Argument::ARGUMENT_VALUE(privilege.c_str()));
818     }
819 }
820 
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