xref: /openbmc/phosphor-user-manager/phosphor-ldap-config/ldap_config.cpp (revision 69570e5eb4114348ab6897a62138fe58336fb53f)
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_t& 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, Ifaces::action::defer_emit),
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_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),
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_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         log<level::ERR>(e.what());
157         elog<InternalFailure>();
158     }
159 }
160 
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 
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/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         log<level::ERR>(e.what());
325         elog<InternalFailure>();
326     }
327     return;
328 }
329 
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         log<level::ERR>(e.what());
352         elog<InternalFailure>();
353     }
354     return value;
355 }
356 
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             log<level::ERR>("bad LDAP Server URI",
377                             entry("LDAPSERVERURI=%s", value.c_str()));
378             elog<InvalidArgument>(Argument::ARGUMENT_NAME("ldapServerURI"),
379                                   Argument::ARGUMENT_VALUE(value.c_str()));
380         }
381 
382         if (secureLDAP && !fs::exists(tlsCacertFile.c_str()))
383         {
384             log<level::ERR>("LDAP server's CA certificate not provided",
385                             entry("TLSCACERTFILE=%s", tlsCacertFile.c_str()));
386             elog<NoCACertificate>();
387         }
388         val = ConfigIface::ldapServerURI(value);
389         if (enabled())
390         {
391             writeConfig();
392             parent.startOrStopService(nslcdService, enabled());
393         }
394         // save the object.
395         serialize();
396     }
397     catch (const InternalFailure& e)
398     {
399         throw;
400     }
401     catch (const InvalidArgument& e)
402     {
403         throw;
404     }
405     catch (const NoCACertificate& e)
406     {
407         throw;
408     }
409     catch (const std::exception& e)
410     {
411         log<level::ERR>(e.what());
412         elog<InternalFailure>();
413     }
414     return val;
415 }
416 
417 std::string Config::ldapBindDN(std::string value)
418 {
419     std::string val;
420     try
421     {
422         if (value == ldapBindDN())
423         {
424             return value;
425         }
426 
427         if (value.empty())
428         {
429             log<level::ERR>("Not a valid LDAP BINDDN",
430                             entry("LDAPBINDDN=%s", value.c_str()));
431             elog<InvalidArgument>(Argument::ARGUMENT_NAME("ldapBindDN"),
432                                   Argument::ARGUMENT_VALUE(value.c_str()));
433         }
434 
435         val = ConfigIface::ldapBindDN(value);
436         if (enabled())
437         {
438             writeConfig();
439             parent.startOrStopService(nslcdService, enabled());
440         }
441         // save the object.
442         serialize();
443     }
444     catch (const InternalFailure& e)
445     {
446         throw;
447     }
448     catch (const InvalidArgument& e)
449     {
450         throw;
451     }
452     catch (const std::exception& e)
453     {
454         log<level::ERR>(e.what());
455         elog<InternalFailure>();
456     }
457     return val;
458 }
459 
460 std::string Config::ldapBaseDN(std::string value)
461 {
462     std::string val;
463     try
464     {
465         if (value == ldapBaseDN())
466         {
467             return value;
468         }
469 
470         if (value.empty())
471         {
472             log<level::ERR>("Not a valid LDAP BASEDN",
473                             entry("BASEDN=%s", value.c_str()));
474             elog<InvalidArgument>(Argument::ARGUMENT_NAME("ldapBaseDN"),
475                                   Argument::ARGUMENT_VALUE(value.c_str()));
476         }
477 
478         val = ConfigIface::ldapBaseDN(value);
479         if (enabled())
480         {
481             writeConfig();
482             parent.startOrStopService(nslcdService, enabled());
483         }
484         // save the object.
485         serialize();
486     }
487     catch (const InternalFailure& e)
488     {
489         throw;
490     }
491     catch (const InvalidArgument& e)
492     {
493         throw;
494     }
495     catch (const std::exception& e)
496     {
497         log<level::ERR>(e.what());
498         elog<InternalFailure>();
499     }
500     return val;
501 }
502 
503 ConfigIface::SearchScope Config::ldapSearchScope(ConfigIface::SearchScope value)
504 {
505     ConfigIface::SearchScope val;
506     try
507     {
508         if (value == ldapSearchScope())
509         {
510             return value;
511         }
512 
513         val = ConfigIface::ldapSearchScope(value);
514         if (enabled())
515         {
516             writeConfig();
517 
518             parent.startOrStopService(nslcdService, enabled());
519         }
520         // save the object.
521         serialize();
522     }
523     catch (const InternalFailure& e)
524     {
525         throw;
526     }
527     catch (const std::exception& e)
528     {
529         log<level::ERR>(e.what());
530         elog<InternalFailure>();
531     }
532     return val;
533 }
534 
535 ConfigIface::Type Config::ldapType(ConfigIface::Type /*value*/)
536 {
537     elog<NotAllowed>(NotAllowedArgument::REASON("ReadOnly Property"));
538     return ldapType();
539 }
540 
541 bool Config::enabled(bool value)
542 {
543     if (value == enabled())
544     {
545         return value;
546     }
547     // Let parent decide that can we enable this config.
548     // It may happen that other config is already enabled,
549     // Current implementation support only one config can
550     // be active at a time.
551     return parent.enableService(*this, value);
552 }
553 
554 bool Config::enableService(bool value)
555 {
556     bool isEnable = false;
557     try
558     {
559         isEnable = EnableIface::enabled(value);
560         if (isEnable)
561         {
562             writeConfig();
563         }
564         parent.startOrStopService(nslcdService, value);
565         serialize();
566     }
567     catch (const InternalFailure& e)
568     {
569         throw;
570     }
571     catch (const std::exception& e)
572     {
573         log<level::ERR>(e.what());
574         elog<InternalFailure>();
575     }
576     return isEnable;
577 }
578 
579 std::string Config::userNameAttribute(std::string value)
580 {
581     std::string val;
582     try
583     {
584         if (value == userNameAttribute())
585         {
586             return value;
587         }
588 
589         val = ConfigIface::userNameAttribute(value);
590         if (enabled())
591         {
592             writeConfig();
593 
594             parent.startOrStopService(nslcdService, enabled());
595         }
596         // save the object.
597         serialize();
598     }
599     catch (const InternalFailure& e)
600     {
601         throw;
602     }
603     catch (const std::exception& e)
604     {
605         log<level::ERR>(e.what());
606         elog<InternalFailure>();
607     }
608     return val;
609 }
610 
611 std::string Config::groupNameAttribute(std::string value)
612 {
613     std::string val;
614     try
615     {
616         if (value == groupNameAttribute())
617         {
618             return value;
619         }
620 
621         val = ConfigIface::groupNameAttribute(value);
622         if (enabled())
623         {
624             writeConfig();
625 
626             parent.startOrStopService(nslcdService, enabled());
627         }
628         // save the object.
629         serialize();
630     }
631     catch (const InternalFailure& e)
632     {
633         throw;
634     }
635     catch (const std::exception& e)
636     {
637         log<level::ERR>(e.what());
638         elog<InternalFailure>();
639     }
640     return val;
641 }
642 
643 template <class Archive>
644 void Config::save(Archive& archive, const std::uint32_t /*version*/) const
645 {
646     archive(this->enabled());
647     archive(ldapServerURI());
648     archive(ldapBindDN());
649     archive(ldapBaseDN());
650     archive(ldapSearchScope());
651     archive(ldapBindPassword);
652     archive(userNameAttribute());
653     archive(groupNameAttribute());
654 }
655 
656 template <class Archive>
657 void Config::load(Archive& archive, const std::uint32_t /*version*/)
658 {
659     bool bVal;
660     archive(bVal);
661     EnableIface::enabled(bVal);
662 
663     std::string str;
664     archive(str);
665     ConfigIface::ldapServerURI(str);
666 
667     archive(str);
668     ConfigIface::ldapBindDN(str);
669 
670     archive(str);
671     ConfigIface::ldapBaseDN(str);
672 
673     ConfigIface::SearchScope scope;
674     archive(scope);
675     ConfigIface::ldapSearchScope(scope);
676 
677     archive(str);
678     ldapBindPassword = str;
679 
680     archive(str);
681     ConfigIface::userNameAttribute(str);
682 
683     archive(str);
684     ConfigIface::groupNameAttribute(str);
685 }
686 
687 void Config::serialize()
688 {
689 
690     if (!fs::exists(configPersistPath.c_str()))
691     {
692         std::ofstream os(configPersistPath.string(),
693                          std::ios::binary | std::ios::out);
694         auto permission = fs::perms::owner_read | fs::perms::owner_write |
695                           fs::perms::group_read;
696         fs::permissions(configPersistPath, permission);
697         cereal::BinaryOutputArchive oarchive(os);
698         oarchive(*this);
699     }
700     else
701     {
702         std::ofstream os(configPersistPath.string(),
703                          std::ios::binary | std::ios::out);
704         cereal::BinaryOutputArchive oarchive(os);
705         oarchive(*this);
706     }
707     return;
708 }
709 
710 bool Config::deserialize()
711 {
712     try
713     {
714         if (fs::exists(configPersistPath))
715         {
716             std::ifstream is(configPersistPath.c_str(),
717                              std::ios::in | std::ios::binary);
718             cereal::BinaryInputArchive iarchive(is);
719             iarchive(*this);
720 
721             if (isValidLDAPURI(ldapServerURI(), LDAPscheme))
722             {
723                 secureLDAP = false;
724             }
725             else if (isValidLDAPURI(ldapServerURI(), LDAPSscheme))
726             {
727                 secureLDAP = true;
728             }
729             return true;
730         }
731         return false;
732     }
733     catch (const cereal::Exception& e)
734     {
735         log<level::ERR>(e.what());
736         std::error_code ec;
737         fs::remove(configPersistPath, ec);
738         return false;
739     }
740     catch (const fs::filesystem_error& e)
741     {
742         return false;
743     }
744 }
745 
746 ObjectPath Config::create(std::string groupName, std::string privilege)
747 {
748     checkPrivilegeMapper(groupName);
749     checkPrivilegeLevel(privilege);
750 
751     entryId++;
752 
753     // Object path for the LDAP group privilege mapper entry
754     fs::path mapperObjectPath = objectPath;
755     mapperObjectPath /= "role_map";
756     mapperObjectPath /= std::to_string(entryId);
757 
758     fs::path persistPath = parent.dbusPersistentPath;
759     persistPath += mapperObjectPath;
760 
761     // Create mapping for LDAP privilege mapper entry
762     auto entry = std::make_unique<LDAPMapperEntry>(
763         bus, mapperObjectPath.string().c_str(), persistPath.string().c_str(),
764         groupName, privilege, *this);
765 
766     phosphor::ldap::serialize(*entry, std::move(persistPath));
767 
768     PrivilegeMapperList.emplace(entryId, std::move(entry));
769     return mapperObjectPath.string();
770 }
771 
772 void Config::deletePrivilegeMapper(Id id)
773 {
774     fs::path mapperObjectPath = objectPath;
775     mapperObjectPath /= "role_map";
776     mapperObjectPath /= std::to_string(id);
777 
778     fs::path persistPath = parent.dbusPersistentPath;
779     persistPath += std::move(mapperObjectPath);
780 
781     // Delete the persistent representation of the privilege mapper.
782     fs::remove(std::move(persistPath));
783 
784     PrivilegeMapperList.erase(id);
785 }
786 void Config::checkPrivilegeMapper(const std::string& groupName)
787 {
788     if (groupName.empty())
789     {
790         log<level::ERR>("Group name is empty");
791         elog<InvalidArgument>(Argument::ARGUMENT_NAME("Group name"),
792                               Argument::ARGUMENT_VALUE("Null"));
793     }
794 
795     for (const auto& val : PrivilegeMapperList)
796     {
797         if (val.second.get()->groupName() == groupName)
798         {
799             log<level::ERR>("Group name already exists");
800             elog<PrivilegeMappingExists>();
801         }
802     }
803 }
804 
805 void Config::checkPrivilegeLevel(const std::string& privilege)
806 {
807     if (privilege.empty())
808     {
809         log<level::ERR>("Privilege level is empty");
810         elog<InvalidArgument>(Argument::ARGUMENT_NAME("Privilege level"),
811                               Argument::ARGUMENT_VALUE("Null"));
812     }
813 
814     if (std::find(privMgr.begin(), privMgr.end(), privilege) == privMgr.end())
815     {
816         log<level::ERR>("Invalid privilege");
817         elog<InvalidArgument>(Argument::ARGUMENT_NAME("Privilege level"),
818                               Argument::ARGUMENT_VALUE(privilege.c_str()));
819     }
820 }
821 
822 void Config::restoreRoleMapping()
823 {
824     namespace fs = std::filesystem;
825     fs::path dir = parent.dbusPersistentPath;
826     dir += objectPath;
827     dir /= "role_map";
828 
829     if (!fs::exists(dir) || fs::is_empty(dir))
830     {
831         return;
832     }
833 
834     for (auto& file : fs::directory_iterator(dir))
835     {
836         std::string id = file.path().filename().c_str();
837         size_t idNum = std::stol(id);
838 
839         auto entryPath = objectPath + '/' + "role_map" + '/' + id;
840         auto persistPath = parent.dbusPersistentPath + entryPath;
841         auto entry = std::make_unique<LDAPMapperEntry>(
842             bus, entryPath.c_str(), persistPath.c_str(), *this);
843         if (phosphor::ldap::deserialize(file.path(), *entry))
844         {
845             entry->Interfaces::emit_object_added();
846             PrivilegeMapperList.emplace(idNum, std::move(entry));
847             if (idNum > entryId)
848             {
849                 entryId = idNum;
850             }
851         }
852     }
853 }
854 
855 } // namespace ldap
856 } // namespace phosphor
857