blob: 80b8c9cb20fc9bf8b18a6876ec46dc9024b9907d [file] [log] [blame]
Ratan Guptae1f4db62019-04-11 18:57:42 +05301#include "ldap_config_mgr.hpp"
Ratan Gupta37fb3fe2019-04-13 12:54:18 +05302#include "ldap_config.hpp"
Nagaraju Goruganti59287f02018-10-12 07:00:20 -05003#include "utils.hpp"
Ratan Gupta21e88cb2019-04-12 17:15:52 +05304
5#include <cereal/types/string.hpp>
6#include <cereal/types/vector.hpp>
7#include <cereal/archives/binary.hpp>
Ratan Gupta7b04c352019-04-12 21:46:29 +05308#include "ldap_mapper_serialize.hpp"
9
10#include <xyz/openbmc_project/Common/error.hpp>
11#include <xyz/openbmc_project/User/Common/error.hpp>
Ratan Gupta95a29312019-02-18 20:34:10 +053012#include <filesystem>
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -050013#include <fstream>
14#include <sstream>
15
Ratan Gupta21e88cb2019-04-12 17:15:52 +053016// Register class version
17// From cereal documentation;
18// "This macro should be placed at global scope"
19CEREAL_CLASS_VERSION(phosphor::ldap::Config, CLASS_VERSION);
20
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -050021namespace phosphor
22{
23namespace ldap
24{
Ratan Guptae1f4db62019-04-11 18:57:42 +053025
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -050026constexpr auto nslcdService = "nslcd.service";
Nagaraju Gorugantidccee2b2018-09-25 08:51:06 -050027constexpr auto nscdService = "nscd.service";
Nagaraju Goruganti59287f02018-10-12 07:00:20 -050028constexpr auto LDAPscheme = "ldap";
29constexpr auto LDAPSscheme = "ldaps";
Ratan Gupta22f13f12019-04-29 15:36:40 +053030constexpr auto certObjPath = "/xyz/openbmc_project/certs/client/ldap";
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -050031
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -050032using namespace phosphor::logging;
33using namespace sdbusplus::xyz::openbmc_project::Common::Error;
Ratan Gupta95a29312019-02-18 20:34:10 +053034namespace fs = std::filesystem;
Ratan Gupta7b04c352019-04-12 21:46:29 +053035
Nagaraju Gorugantib26799a2018-09-28 13:12:19 -050036using Argument = xyz::openbmc_project::Common::InvalidArgument;
Ratan Gupta27d4c012019-04-12 13:03:35 +053037using NotAllowed = sdbusplus::xyz::openbmc_project::Common::Error::NotAllowed;
38using NotAllowedArgument = xyz::openbmc_project::Common::NotAllowed;
Ratan Gupta7b04c352019-04-12 21:46:29 +053039using PrivilegeMappingExists = sdbusplus::xyz::openbmc_project::User::Common::
40 Error::PrivilegeMappingExists;
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -050041
42using Line = std::string;
43using Key = std::string;
44using Val = std::string;
45using ConfigInfo = std::map<Key, Val>;
46
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -050047Config::Config(sdbusplus::bus::bus& bus, const char* path, const char* filePath,
Ratan Gupta22f13f12019-04-29 15:36:40 +053048 const char* caCertFile, const char* certFile, bool secureLDAP,
Nagaraju Goruganti3b4d06a2018-11-08 03:13:38 -060049 std::string lDAPServerURI, std::string lDAPBindDN,
50 std::string lDAPBaseDN, std::string&& lDAPBindDNPassword,
Ratan Guptaaeaf9412019-02-11 04:41:52 -060051 ConfigIface::SearchScope lDAPSearchScope,
52 ConfigIface::Type lDAPType, bool lDAPServiceEnabled,
53 std::string userNameAttr, std::string groupNameAttr,
54 ConfigMgr& parent) :
55 Ifaces(bus, path, true),
Ratan Gupta3a1c2742019-03-20 06:49:42 +053056 secureLDAP(secureLDAP), lDAPBindPassword(std::move(lDAPBindDNPassword)),
Ratan Gupta22f13f12019-04-29 15:36:40 +053057 tlsCacertFile(caCertFile), tlsCertFile(certFile), configFilePath(filePath),
58 objectPath(path), bus(bus), parent(parent),
59 certificateInstalledSignal(
60 bus, sdbusplus::bus::match::rules::interfacesAdded(certObjPath),
61 std::bind(std::mem_fn(&Config::certificateInstalled), this,
62 std::placeholders::_1))
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -050063{
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -050064 ConfigIface::lDAPServerURI(lDAPServerURI);
65 ConfigIface::lDAPBindDN(lDAPBindDN);
66 ConfigIface::lDAPBaseDN(lDAPBaseDN);
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -050067 ConfigIface::lDAPSearchScope(lDAPSearchScope);
68 ConfigIface::lDAPType(lDAPType);
Ratan Guptaaeaf9412019-02-11 04:41:52 -060069 EnableIface::enabled(lDAPServiceEnabled);
70 ConfigIface::userNameAttribute(userNameAttr);
71 ConfigIface::groupNameAttribute(groupNameAttr);
Ratan Gupta21e88cb2019-04-12 17:15:52 +053072 // NOTE: Don't update the bindDN password under ConfigIface
Ratan Guptaec117542019-04-25 18:38:29 +053073 if (enabled())
74 {
75 writeConfig();
76 }
Ratan Gupta21e88cb2019-04-12 17:15:52 +053077 // save the config.
78 configPersistPath = parent.dbusPersistentPath;
79 configPersistPath += objectPath;
80
81 // create the persistent directory
82 fs::create_directories(configPersistPath);
83
84 configPersistPath += "/config";
85
86 std::ofstream os(configPersistPath, std::ios::binary | std::ios::out);
87 // remove the read permission from others
88 auto permission =
89 fs::perms::owner_read | fs::perms::owner_write | fs::perms::group_read;
90 fs::permissions(configPersistPath, permission);
91
92 serialize();
93
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -050094 // Emit deferred signal.
95 this->emit_object_added();
Ratan Guptaaeaf9412019-02-11 04:41:52 -060096 parent.startOrStopService(nslcdService, enabled());
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -050097}
98
Ratan Gupta21e88cb2019-04-12 17:15:52 +053099Config::Config(sdbusplus::bus::bus& bus, const char* path, const char* filePath,
100 const char* caCertFile, ConfigIface::Type lDAPType,
101 ConfigMgr& parent) :
102 Ifaces(bus, path, true),
103 tlsCacertFile(caCertFile), configFilePath(filePath), objectPath(path),
Ratan Gupta22f13f12019-04-29 15:36:40 +0530104 bus(bus), parent(parent),
105 certificateInstalledSignal(
106 bus, sdbusplus::bus::match::rules::interfacesAdded(certObjPath),
107 std::bind(std::mem_fn(&Config::certificateInstalled), this,
108 std::placeholders::_1))
Ratan Gupta21e88cb2019-04-12 17:15:52 +0530109{
110 ConfigIface::lDAPType(lDAPType);
111
112 configPersistPath = parent.dbusPersistentPath;
113 configPersistPath += objectPath;
114
115 // create the persistent directory
116 fs::create_directories(configPersistPath);
117
118 configPersistPath += "/config";
119
120 std::ofstream os(configPersistPath, std::ios::binary | std::ios::out);
121 // remove the read permission from others
122 auto permission =
123 fs::perms::owner_read | fs::perms::owner_write | fs::perms::group_read;
124 fs::permissions(configPersistPath, permission);
125}
126
Ratan Gupta22f13f12019-04-29 15:36:40 +0530127void Config::certificateInstalled(sdbusplus::message::message& msg)
128{
129 try
130 {
131 if (enabled())
132 {
133 writeConfig();
134 }
135 parent.startOrStopService(nslcdService, enabled());
136 }
137 catch (const InternalFailure& e)
138 {
139 throw;
140 }
141 catch (const std::exception& e)
142 {
143 log<level::ERR>(e.what());
144 elog<InternalFailure>();
145 }
146}
147
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500148void Config::writeConfig()
149{
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500150 std::stringstream confData;
Ratan Gupta9891f2f2018-10-06 12:07:35 +0530151 auto isPwdTobeWritten = false;
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600152 std::string userNameAttr;
Ratan Gupta9891f2f2018-10-06 12:07:35 +0530153
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500154 confData << "uid root\n";
155 confData << "gid root\n\n";
156 confData << "ldap_version 3\n\n";
157 confData << "timelimit 30\n";
158 confData << "bind_timelimit 30\n";
159 confData << "pagesize 1000\n";
160 confData << "referrals off\n\n";
161 confData << "uri " << lDAPServerURI() << "\n\n";
162 confData << "base " << lDAPBaseDN() << "\n\n";
163 confData << "binddn " << lDAPBindDN() << "\n";
Ratan Gupta3a1c2742019-03-20 06:49:42 +0530164 if (!lDAPBindPassword.empty())
Nagaraju Goruganti15675472018-10-05 07:03:05 -0500165 {
Ratan Gupta3a1c2742019-03-20 06:49:42 +0530166 confData << "bindpw " << lDAPBindPassword << "\n";
Ratan Gupta9891f2f2018-10-06 12:07:35 +0530167 isPwdTobeWritten = true;
Nagaraju Goruganti15675472018-10-05 07:03:05 -0500168 }
169 confData << "\n";
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500170 switch (lDAPSearchScope())
171 {
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600172 case ConfigIface::SearchScope::sub:
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500173 confData << "scope sub\n\n";
174 break;
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600175 case ConfigIface::SearchScope::one:
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500176 confData << "scope one\n\n";
177 break;
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600178 case ConfigIface::SearchScope::base:
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500179 confData << "scope base\n\n";
180 break;
181 }
182 confData << "base passwd " << lDAPBaseDN() << "\n";
183 confData << "base shadow " << lDAPBaseDN() << "\n\n";
Nagaraju Gorugantidb60f582018-11-08 03:14:48 -0600184 if (secureLDAP == true)
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500185 {
186 confData << "ssl on\n";
Nagaraju Goruganti3b4d06a2018-11-08 03:13:38 -0600187 confData << "tls_reqcert hard\n";
188 confData << "tls_cacertFile " << tlsCacertFile.c_str() << "\n";
Ratan Gupta22f13f12019-04-29 15:36:40 +0530189 if (fs::exists(tlsCertFile.c_str()))
190 {
191 confData << "tls_cert " << tlsCertFile.c_str() << "\n";
192 confData << "tls_key " << tlsCertFile.c_str() << "\n";
193 }
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500194 }
195 else
196 {
Nagaraju Goruganti15675472018-10-05 07:03:05 -0500197 confData << "ssl off\n";
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500198 }
Nagaraju Goruganti15675472018-10-05 07:03:05 -0500199 confData << "\n";
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600200 if (lDAPType() == ConfigIface::Type::ActiveDirectory)
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500201 {
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600202 if (ConfigIface::userNameAttribute().empty())
203 {
204 ConfigIface::userNameAttribute("sAMAccountName");
205 }
206 if (ConfigIface::groupNameAttribute().empty())
207 {
208 ConfigIface::groupNameAttribute("primaryGroupID");
209 }
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500210 confData << "filter passwd (&(objectClass=user)(objectClass=person)"
211 "(!(objectClass=computer)))\n";
212 confData
213 << "filter group (|(objectclass=group)(objectclass=groupofnames) "
214 "(objectclass=groupofuniquenames))\n";
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600215 confData << "map passwd uid "
216 << ConfigIface::userNameAttribute() << "\n";
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500217 confData << "map passwd uidNumber "
218 "objectSid:S-1-5-21-3623811015-3361044348-30300820\n";
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600219 confData << "map passwd gidNumber "
220 << ConfigIface::groupNameAttribute() << "\n";
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500221 confData << "map passwd homeDirectory \"/home/$sAMAccountName\"\n";
222 confData << "map passwd gecos displayName\n";
223 confData << "map passwd loginShell \"/bin/bash\"\n";
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500224 confData << "map group gidNumber "
225 "objectSid:S-1-5-21-3623811015-3361044348-30300820\n";
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600226 confData << "map group cn "
227 << ConfigIface::userNameAttribute() << "\n";
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500228 }
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600229 else if (lDAPType() == ConfigIface::Type::OpenLdap)
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500230 {
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600231 if (ConfigIface::userNameAttribute().empty())
232 {
raviteja-bc3f56c52019-04-02 11:09:04 -0500233 ConfigIface::userNameAttribute("cn");
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600234 }
235 if (ConfigIface::groupNameAttribute().empty())
236 {
raviteja-bc3f56c52019-04-02 11:09:04 -0500237 ConfigIface::groupNameAttribute("gidNumber");
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600238 }
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500239 confData << "filter passwd (objectclass=*)\n";
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500240 confData << "map passwd gecos displayName\n";
Nagaraju Goruganti808eda42018-10-10 08:48:12 -0500241 confData << "filter group (objectclass=posixGroup)\n";
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600242 confData << "map passwd uid "
243 << ConfigIface::userNameAttribute() << "\n";
244 confData << "map passwd gidNumber "
245 << ConfigIface::groupNameAttribute() << "\n";
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500246 }
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500247 try
248 {
249 std::fstream stream(configFilePath.c_str(), std::fstream::out);
Ratan Gupta9891f2f2018-10-06 12:07:35 +0530250 // remove the read permission from others if password is being written.
251 // nslcd forces this behaviour.
252 auto permission = fs::perms::owner_read | fs::perms::owner_write |
253 fs::perms::group_read;
254 if (isPwdTobeWritten)
255 {
256 fs::permissions(configFilePath, permission);
257 }
258 else
259 {
260 fs::permissions(configFilePath,
261 permission | fs::perms::others_read);
262 }
263
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500264 stream << confData.str();
265 stream.flush();
266 stream.close();
267 }
268 catch (const std::exception& e)
269 {
270 log<level::ERR>(e.what());
271 elog<InternalFailure>();
272 }
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500273 return;
274}
275
Ratan Gupta3a1c2742019-03-20 06:49:42 +0530276std::string Config::lDAPBindDNPassword(std::string value)
277{
278 // Don't update the D-bus object, this is just to
279 // facilitate if user wants to change the bind dn password
280 // once d-bus object gets created.
281 lDAPBindPassword = value;
282 try
283 {
Ratan Guptaec117542019-04-25 18:38:29 +0530284 if (enabled())
285 {
286 writeConfig();
287 parent.startOrStopService(nslcdService, enabled());
288 }
Ratan Gupta21e88cb2019-04-12 17:15:52 +0530289 serialize();
Ratan Gupta3a1c2742019-03-20 06:49:42 +0530290 }
291 catch (const InternalFailure& e)
292 {
293 throw;
294 }
295 catch (const std::exception& e)
296 {
297 log<level::ERR>(e.what());
298 elog<InternalFailure>();
299 }
300 return value;
301}
302
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500303std::string Config::lDAPServerURI(std::string value)
304{
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500305 std::string val;
306 try
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500307 {
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500308 if (value == lDAPServerURI())
309 {
310 return value;
311 }
Nagaraju Goruganti59287f02018-10-12 07:00:20 -0500312 if (isValidLDAPURI(value, LDAPSscheme))
Nagaraju Gorugantib26799a2018-09-28 13:12:19 -0500313 {
Nagaraju Goruganti59287f02018-10-12 07:00:20 -0500314 secureLDAP = true;
315 }
316 else if (isValidLDAPURI(value, LDAPscheme))
317 {
318 secureLDAP = false;
Nagaraju Gorugantidb60f582018-11-08 03:14:48 -0600319 }
320 else
321 {
Nagaraju Goruganti59287f02018-10-12 07:00:20 -0500322 log<level::ERR>("bad LDAP Server URI",
323 entry("LDAPSERVERURI=%s", value.c_str()));
324 elog<InvalidArgument>(Argument::ARGUMENT_NAME("lDAPServerURI"),
325 Argument::ARGUMENT_VALUE(value.c_str()));
Nagaraju Gorugantib26799a2018-09-28 13:12:19 -0500326 }
Nagaraju Goruganti3b4d06a2018-11-08 03:13:38 -0600327
328 if (secureLDAP && !fs::exists(tlsCacertFile.c_str()))
329 {
330 log<level::ERR>("LDAP server's CA certificate not provided",
331 entry("TLSCACERTFILE=%s", tlsCacertFile.c_str()));
332 elog<NoCACertificate>();
333 }
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500334 val = ConfigIface::lDAPServerURI(value);
Ratan Guptaec117542019-04-25 18:38:29 +0530335 if (enabled())
336 {
337 writeConfig();
338 parent.startOrStopService(nslcdService, enabled());
339 }
Ratan Gupta21e88cb2019-04-12 17:15:52 +0530340 // save the object.
341 serialize();
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500342 }
343 catch (const InternalFailure& e)
344 {
345 throw;
346 }
Nagaraju Goruganti59287f02018-10-12 07:00:20 -0500347 catch (const InvalidArgument& e)
348 {
349 throw;
350 }
Nagaraju Goruganti3b4d06a2018-11-08 03:13:38 -0600351 catch (const NoCACertificate& e)
352 {
353 throw;
354 }
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500355 catch (const std::exception& e)
356 {
357 log<level::ERR>(e.what());
358 elog<InternalFailure>();
359 }
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500360 return val;
361}
362
363std::string Config::lDAPBindDN(std::string value)
364{
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500365 std::string val;
366 try
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500367 {
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500368 if (value == lDAPBindDN())
369 {
370 return value;
371 }
372
Nagaraju Gorugantib26799a2018-09-28 13:12:19 -0500373 if (value.empty())
374 {
Nagaraju Goruganti59287f02018-10-12 07:00:20 -0500375 log<level::ERR>("Not a valid LDAP BINDDN",
376 entry("LDAPBINDDN=%s", value.c_str()));
Nagaraju Gorugantib26799a2018-09-28 13:12:19 -0500377 elog<InvalidArgument>(Argument::ARGUMENT_NAME("lDAPBindDN"),
378 Argument::ARGUMENT_VALUE(value.c_str()));
379 }
380
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500381 val = ConfigIface::lDAPBindDN(value);
Ratan Guptaec117542019-04-25 18:38:29 +0530382 if (enabled())
383 {
384 writeConfig();
385 parent.startOrStopService(nslcdService, enabled());
386 }
Ratan Gupta21e88cb2019-04-12 17:15:52 +0530387 // save the object.
388 serialize();
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500389 }
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500390 catch (const InternalFailure& e)
391 {
392 throw;
393 }
Nagaraju Gorugantid514e5d2018-11-08 03:07:25 -0600394 catch (const InvalidArgument& e)
395 {
396 throw;
397 }
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500398 catch (const std::exception& e)
399 {
400 log<level::ERR>(e.what());
401 elog<InternalFailure>();
402 }
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500403 return val;
404}
405
406std::string Config::lDAPBaseDN(std::string value)
407{
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500408 std::string val;
409 try
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500410 {
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500411 if (value == lDAPBaseDN())
412 {
413 return value;
414 }
415
Nagaraju Gorugantib26799a2018-09-28 13:12:19 -0500416 if (value.empty())
417 {
Nagaraju Goruganti59287f02018-10-12 07:00:20 -0500418 log<level::ERR>("Not a valid LDAP BASEDN",
419 entry("BASEDN=%s", value.c_str()));
Nagaraju Gorugantib26799a2018-09-28 13:12:19 -0500420 elog<InvalidArgument>(Argument::ARGUMENT_NAME("lDAPBaseDN"),
421 Argument::ARGUMENT_VALUE(value.c_str()));
422 }
423
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500424 val = ConfigIface::lDAPBaseDN(value);
Ratan Guptaec117542019-04-25 18:38:29 +0530425 if (enabled())
426 {
427 writeConfig();
428 parent.startOrStopService(nslcdService, enabled());
429 }
Ratan Gupta21e88cb2019-04-12 17:15:52 +0530430 // save the object.
431 serialize();
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500432 }
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500433 catch (const InternalFailure& e)
434 {
435 throw;
436 }
Nagaraju Gorugantid514e5d2018-11-08 03:07:25 -0600437 catch (const InvalidArgument& e)
438 {
439 throw;
440 }
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500441 catch (const std::exception& e)
442 {
443 log<level::ERR>(e.what());
444 elog<InternalFailure>();
445 }
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500446 return val;
447}
448
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600449ConfigIface::SearchScope Config::lDAPSearchScope(ConfigIface::SearchScope value)
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500450{
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600451 ConfigIface::SearchScope val;
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500452 try
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500453 {
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500454 if (value == lDAPSearchScope())
455 {
456 return value;
457 }
458
459 val = ConfigIface::lDAPSearchScope(value);
Ratan Guptaec117542019-04-25 18:38:29 +0530460 if (enabled())
461 {
462 writeConfig();
463
464 parent.startOrStopService(nslcdService, enabled());
465 }
Ratan Gupta21e88cb2019-04-12 17:15:52 +0530466 // save the object.
467 serialize();
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500468 }
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500469 catch (const InternalFailure& e)
470 {
471 throw;
472 }
473 catch (const std::exception& e)
474 {
475 log<level::ERR>(e.what());
476 elog<InternalFailure>();
477 }
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500478 return val;
479}
480
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600481ConfigIface::Type Config::lDAPType(ConfigIface::Type value)
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500482{
Ratan Gupta27d4c012019-04-12 13:03:35 +0530483 elog<NotAllowed>(NotAllowedArgument::REASON("ReadOnly Property"));
484 return lDAPType();
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500485}
486
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600487bool Config::enabled(bool value)
488{
Ratan Guptac5481d12019-04-12 18:31:05 +0530489 if (value == enabled())
490 {
491 return value;
492 }
493 // Let parent decide that can we enable this config.
494 // It may happen that other config is already enabled,
495 // Current implementation support only one config can
496 // be active at a time.
497 return parent.enableService(*this, value);
498}
499
500bool Config::enableService(bool value)
501{
502 bool isEnable = false;
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600503 try
504 {
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600505 isEnable = EnableIface::enabled(value);
Ratan Guptaec117542019-04-25 18:38:29 +0530506 if (isEnable)
507 {
508 writeConfig();
509 }
Ratan Guptaec117542019-04-25 18:38:29 +0530510 parent.startOrStopService(nslcdService, value);
Ratan Gupta21e88cb2019-04-12 17:15:52 +0530511 serialize();
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600512 }
513 catch (const InternalFailure& e)
514 {
515 throw;
516 }
517 catch (const std::exception& e)
518 {
519 log<level::ERR>(e.what());
520 elog<InternalFailure>();
521 }
522 return isEnable;
523}
524
525std::string Config::userNameAttribute(std::string value)
526{
527 std::string val;
528 try
529 {
530 if (value == userNameAttribute())
531 {
532 return value;
533 }
534
535 val = ConfigIface::userNameAttribute(value);
Ratan Guptaec117542019-04-25 18:38:29 +0530536 if (enabled())
537 {
538 writeConfig();
539
540 parent.startOrStopService(nslcdService, enabled());
541 }
Ratan Gupta21e88cb2019-04-12 17:15:52 +0530542 // save the object.
543 serialize();
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600544 }
545 catch (const InternalFailure& e)
546 {
547 throw;
548 }
549 catch (const std::exception& e)
550 {
551 log<level::ERR>(e.what());
552 elog<InternalFailure>();
553 }
554 return val;
555}
556
557std::string Config::groupNameAttribute(std::string value)
558{
559 std::string val;
560 try
561 {
562 if (value == groupNameAttribute())
563 {
564 return value;
565 }
566
567 val = ConfigIface::groupNameAttribute(value);
Ratan Guptaec117542019-04-25 18:38:29 +0530568 if (enabled())
569 {
570 writeConfig();
571
572 parent.startOrStopService(nslcdService, enabled());
573 }
Ratan Gupta21e88cb2019-04-12 17:15:52 +0530574 // save the object.
575 serialize();
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600576 }
577 catch (const InternalFailure& e)
578 {
579 throw;
580 }
581 catch (const std::exception& e)
582 {
583 log<level::ERR>(e.what());
584 elog<InternalFailure>();
585 }
586 return val;
587}
588
Ratan Gupta21e88cb2019-04-12 17:15:52 +0530589template <class Archive>
590void Config::save(Archive& archive, const std::uint32_t version) const
591{
592 archive(this->enabled());
593 archive(lDAPServerURI());
594 archive(lDAPBindDN());
595 archive(lDAPBaseDN());
596 archive(lDAPSearchScope());
597 archive(lDAPBindPassword);
598 archive(userNameAttribute());
599 archive(groupNameAttribute());
600}
601
602template <class Archive>
603void Config::load(Archive& archive, const std::uint32_t version)
604{
605
606 bool bVal;
607 archive(bVal);
608 EnableIface::enabled(bVal);
609
610 std::string str;
611 archive(str);
612 ConfigIface::lDAPServerURI(str);
613
614 archive(str);
615 ConfigIface::lDAPBindDN(str);
616
617 archive(str);
618 ConfigIface::lDAPBaseDN(str);
619
620 ConfigIface::SearchScope scope;
621 archive(scope);
622 ConfigIface::lDAPSearchScope(scope);
623
624 archive(str);
625 lDAPBindPassword = str;
626
627 archive(str);
628 ConfigIface::userNameAttribute(str);
629
630 archive(str);
631 ConfigIface::groupNameAttribute(str);
632}
633
634void Config::serialize()
635{
636 std::ofstream os(configPersistPath.string(),
637 std::ios::binary | std::ios::out);
638 cereal::BinaryOutputArchive oarchive(os);
639 oarchive(*this);
640 return;
641}
642
643bool Config::deserialize()
644{
645 try
646 {
647 if (fs::exists(configPersistPath))
648 {
649 std::ifstream is(configPersistPath.c_str(),
650 std::ios::in | std::ios::binary);
651 cereal::BinaryInputArchive iarchive(is);
652 iarchive(*this);
653 return true;
654 }
655 return false;
656 }
657 catch (cereal::Exception& e)
658 {
659 log<level::ERR>(e.what());
660 std::error_code ec;
661 fs::remove(configPersistPath, ec);
662 return false;
663 }
664 catch (const fs::filesystem_error& e)
665 {
666 return false;
667 }
668}
669
Ratan Gupta7b04c352019-04-12 21:46:29 +0530670ObjectPath Config::create(std::string groupName, std::string privilege)
671{
672 checkPrivilegeMapper(groupName);
673 checkPrivilegeLevel(privilege);
674
675 entryId++;
676
677 // Object path for the LDAP group privilege mapper entry
678 fs::path mapperObjectPath = objectPath;
679 mapperObjectPath /= "role_map";
680 mapperObjectPath /= std::to_string(entryId);
681
682 fs::path persistPath = parent.dbusPersistentPath;
683 persistPath += mapperObjectPath;
684
685 // Create mapping for LDAP privilege mapper entry
686 auto entry = std::make_unique<LDAPMapperEntry>(
687 bus, mapperObjectPath.string().c_str(), persistPath.string().c_str(),
688 groupName, privilege, *this);
689
690 phosphor::ldap::serialize(*entry, std::move(persistPath));
691
692 PrivilegeMapperList.emplace(entryId, std::move(entry));
693 return mapperObjectPath.string();
694}
695
696void Config::deletePrivilegeMapper(Id id)
697{
698 fs::path mapperObjectPath = objectPath;
699 mapperObjectPath /= "role_map";
700 mapperObjectPath /= std::to_string(id);
701
702 fs::path persistPath = parent.dbusPersistentPath;
703 persistPath += std::move(mapperObjectPath);
704
705 // Delete the persistent representation of the privilege mapper.
706 fs::remove(std::move(persistPath));
707
708 PrivilegeMapperList.erase(id);
709}
710void Config::checkPrivilegeMapper(const std::string& groupName)
711{
712 if (groupName.empty())
713 {
714 log<level::ERR>("Group name is empty");
715 elog<InvalidArgument>(Argument::ARGUMENT_NAME("Group name"),
716 Argument::ARGUMENT_VALUE("Null"));
717 }
718
719 for (const auto& val : PrivilegeMapperList)
720 {
721 if (val.second.get()->groupName() == groupName)
722 {
723 log<level::ERR>("Group name already exists");
724 elog<PrivilegeMappingExists>();
725 }
726 }
727}
728
729void Config::checkPrivilegeLevel(const std::string& privilege)
730{
731 if (privilege.empty())
732 {
733 log<level::ERR>("Privilege level is empty");
734 elog<InvalidArgument>(Argument::ARGUMENT_NAME("Privilege level"),
735 Argument::ARGUMENT_VALUE("Null"));
736 }
737
738 if (std::find(privMgr.begin(), privMgr.end(), privilege) == privMgr.end())
739 {
740 log<level::ERR>("Invalid privilege");
741 elog<InvalidArgument>(Argument::ARGUMENT_NAME("Privilege level"),
742 Argument::ARGUMENT_VALUE(privilege.c_str()));
743 }
744}
745
746void Config::restoreRoleMapping()
747{
748 namespace fs = std::filesystem;
749 fs::path dir = parent.dbusPersistentPath;
750 dir += objectPath;
751 dir /= "role_map";
752
753 if (!fs::exists(dir) || fs::is_empty(dir))
754 {
755 return;
756 }
757
758 for (auto& file : fs::directory_iterator(dir))
759 {
760 std::string id = file.path().filename().c_str();
761 size_t idNum = std::stol(id);
762
763 auto entryPath = objectPath + '/' + "role_map" + '/' + id;
764 auto persistPath = parent.dbusPersistentPath + entryPath;
765 auto entry = std::make_unique<LDAPMapperEntry>(
766 bus, entryPath.c_str(), persistPath.c_str(), *this);
767 if (phosphor::ldap::deserialize(file.path(), *entry))
768 {
769 entry->Interfaces::emit_object_added();
770 PrivilegeMapperList.emplace(idNum, std::move(entry));
771 if (idNum > entryId)
772 {
773 entryId = idNum;
774 }
775 }
776 }
777}
778
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500779} // namespace ldap
780} // namespace phosphor