blob: b22d6846e62a1cfcbda3f3d9ec2d34d25cd990e8 [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";
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -050030
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -050031using namespace phosphor::logging;
32using namespace sdbusplus::xyz::openbmc_project::Common::Error;
Ratan Gupta95a29312019-02-18 20:34:10 +053033namespace fs = std::filesystem;
Ratan Gupta7b04c352019-04-12 21:46:29 +053034
Nagaraju Gorugantib26799a2018-09-28 13:12:19 -050035using Argument = xyz::openbmc_project::Common::InvalidArgument;
Ratan Gupta27d4c012019-04-12 13:03:35 +053036using NotAllowed = sdbusplus::xyz::openbmc_project::Common::Error::NotAllowed;
37using NotAllowedArgument = xyz::openbmc_project::Common::NotAllowed;
Ratan Gupta7b04c352019-04-12 21:46:29 +053038using PrivilegeMappingExists = sdbusplus::xyz::openbmc_project::User::Common::
39 Error::PrivilegeMappingExists;
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -050040
41using Line = std::string;
42using Key = std::string;
43using Val = std::string;
44using ConfigInfo = std::map<Key, Val>;
45
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -050046Config::Config(sdbusplus::bus::bus& bus, const char* path, const char* filePath,
Nagaraju Goruganti3b4d06a2018-11-08 03:13:38 -060047 const char* caCertFile, bool secureLDAP,
48 std::string lDAPServerURI, std::string lDAPBindDN,
49 std::string lDAPBaseDN, std::string&& lDAPBindDNPassword,
Ratan Guptaaeaf9412019-02-11 04:41:52 -060050 ConfigIface::SearchScope lDAPSearchScope,
51 ConfigIface::Type lDAPType, bool lDAPServiceEnabled,
52 std::string userNameAttr, std::string groupNameAttr,
53 ConfigMgr& parent) :
54 Ifaces(bus, path, true),
Ratan Gupta3a1c2742019-03-20 06:49:42 +053055 secureLDAP(secureLDAP), lDAPBindPassword(std::move(lDAPBindDNPassword)),
Ratan Gupta21e88cb2019-04-12 17:15:52 +053056 tlsCacertFile(caCertFile), configFilePath(filePath), objectPath(path),
57 bus(bus), parent(parent)
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -050058{
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -050059 ConfigIface::lDAPServerURI(lDAPServerURI);
60 ConfigIface::lDAPBindDN(lDAPBindDN);
61 ConfigIface::lDAPBaseDN(lDAPBaseDN);
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -050062 ConfigIface::lDAPSearchScope(lDAPSearchScope);
63 ConfigIface::lDAPType(lDAPType);
Ratan Guptaaeaf9412019-02-11 04:41:52 -060064 EnableIface::enabled(lDAPServiceEnabled);
65 ConfigIface::userNameAttribute(userNameAttr);
66 ConfigIface::groupNameAttribute(groupNameAttr);
Ratan Gupta21e88cb2019-04-12 17:15:52 +053067 // NOTE: Don't update the bindDN password under ConfigIface
Ratan Guptaec117542019-04-25 18:38:29 +053068 if (enabled())
69 {
70 writeConfig();
71 }
Ratan Gupta21e88cb2019-04-12 17:15:52 +053072 // save the config.
73 configPersistPath = parent.dbusPersistentPath;
74 configPersistPath += objectPath;
75
76 // create the persistent directory
77 fs::create_directories(configPersistPath);
78
79 configPersistPath += "/config";
80
81 std::ofstream os(configPersistPath, std::ios::binary | std::ios::out);
82 // remove the read permission from others
83 auto permission =
84 fs::perms::owner_read | fs::perms::owner_write | fs::perms::group_read;
85 fs::permissions(configPersistPath, permission);
86
87 serialize();
88
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -050089 // Emit deferred signal.
90 this->emit_object_added();
Ratan Guptaaeaf9412019-02-11 04:41:52 -060091 parent.startOrStopService(nslcdService, enabled());
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -050092}
93
Ratan Gupta21e88cb2019-04-12 17:15:52 +053094Config::Config(sdbusplus::bus::bus& bus, const char* path, const char* filePath,
95 const char* caCertFile, ConfigIface::Type lDAPType,
96 ConfigMgr& parent) :
97 Ifaces(bus, path, true),
98 tlsCacertFile(caCertFile), configFilePath(filePath), objectPath(path),
99 bus(bus), parent(parent)
100{
101 ConfigIface::lDAPType(lDAPType);
102
103 configPersistPath = parent.dbusPersistentPath;
104 configPersistPath += objectPath;
105
106 // create the persistent directory
107 fs::create_directories(configPersistPath);
108
109 configPersistPath += "/config";
110
111 std::ofstream os(configPersistPath, std::ios::binary | std::ios::out);
112 // remove the read permission from others
113 auto permission =
114 fs::perms::owner_read | fs::perms::owner_write | fs::perms::group_read;
115 fs::permissions(configPersistPath, permission);
116}
117
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500118void Config::writeConfig()
119{
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500120 std::stringstream confData;
Ratan Gupta9891f2f2018-10-06 12:07:35 +0530121 auto isPwdTobeWritten = false;
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600122 std::string userNameAttr;
Ratan Gupta9891f2f2018-10-06 12:07:35 +0530123
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500124 confData << "uid root\n";
125 confData << "gid root\n\n";
126 confData << "ldap_version 3\n\n";
127 confData << "timelimit 30\n";
128 confData << "bind_timelimit 30\n";
129 confData << "pagesize 1000\n";
130 confData << "referrals off\n\n";
131 confData << "uri " << lDAPServerURI() << "\n\n";
132 confData << "base " << lDAPBaseDN() << "\n\n";
133 confData << "binddn " << lDAPBindDN() << "\n";
Ratan Gupta3a1c2742019-03-20 06:49:42 +0530134 if (!lDAPBindPassword.empty())
Nagaraju Goruganti15675472018-10-05 07:03:05 -0500135 {
Ratan Gupta3a1c2742019-03-20 06:49:42 +0530136 confData << "bindpw " << lDAPBindPassword << "\n";
Ratan Gupta9891f2f2018-10-06 12:07:35 +0530137 isPwdTobeWritten = true;
Nagaraju Goruganti15675472018-10-05 07:03:05 -0500138 }
139 confData << "\n";
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500140 switch (lDAPSearchScope())
141 {
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600142 case ConfigIface::SearchScope::sub:
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500143 confData << "scope sub\n\n";
144 break;
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600145 case ConfigIface::SearchScope::one:
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500146 confData << "scope one\n\n";
147 break;
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600148 case ConfigIface::SearchScope::base:
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500149 confData << "scope base\n\n";
150 break;
151 }
152 confData << "base passwd " << lDAPBaseDN() << "\n";
153 confData << "base shadow " << lDAPBaseDN() << "\n\n";
Nagaraju Gorugantidb60f582018-11-08 03:14:48 -0600154 if (secureLDAP == true)
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500155 {
156 confData << "ssl on\n";
Nagaraju Goruganti3b4d06a2018-11-08 03:13:38 -0600157 confData << "tls_reqcert hard\n";
158 confData << "tls_cacertFile " << tlsCacertFile.c_str() << "\n";
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500159 }
160 else
161 {
Nagaraju Goruganti15675472018-10-05 07:03:05 -0500162 confData << "ssl off\n";
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500163 }
Nagaraju Goruganti15675472018-10-05 07:03:05 -0500164 confData << "\n";
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600165 if (lDAPType() == ConfigIface::Type::ActiveDirectory)
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500166 {
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600167 if (ConfigIface::userNameAttribute().empty())
168 {
169 ConfigIface::userNameAttribute("sAMAccountName");
170 }
171 if (ConfigIface::groupNameAttribute().empty())
172 {
173 ConfigIface::groupNameAttribute("primaryGroupID");
174 }
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500175 confData << "filter passwd (&(objectClass=user)(objectClass=person)"
176 "(!(objectClass=computer)))\n";
177 confData
178 << "filter group (|(objectclass=group)(objectclass=groupofnames) "
179 "(objectclass=groupofuniquenames))\n";
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600180 confData << "map passwd uid "
181 << ConfigIface::userNameAttribute() << "\n";
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500182 confData << "map passwd uidNumber "
183 "objectSid:S-1-5-21-3623811015-3361044348-30300820\n";
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600184 confData << "map passwd gidNumber "
185 << ConfigIface::groupNameAttribute() << "\n";
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500186 confData << "map passwd homeDirectory \"/home/$sAMAccountName\"\n";
187 confData << "map passwd gecos displayName\n";
188 confData << "map passwd loginShell \"/bin/bash\"\n";
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500189 confData << "map group gidNumber "
190 "objectSid:S-1-5-21-3623811015-3361044348-30300820\n";
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600191 confData << "map group cn "
192 << ConfigIface::userNameAttribute() << "\n";
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500193 }
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600194 else if (lDAPType() == ConfigIface::Type::OpenLdap)
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500195 {
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600196 if (ConfigIface::userNameAttribute().empty())
197 {
raviteja-bc3f56c52019-04-02 11:09:04 -0500198 ConfigIface::userNameAttribute("cn");
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600199 }
200 if (ConfigIface::groupNameAttribute().empty())
201 {
raviteja-bc3f56c52019-04-02 11:09:04 -0500202 ConfigIface::groupNameAttribute("gidNumber");
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600203 }
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500204 confData << "filter passwd (objectclass=*)\n";
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500205 confData << "map passwd gecos displayName\n";
Nagaraju Goruganti808eda42018-10-10 08:48:12 -0500206 confData << "filter group (objectclass=posixGroup)\n";
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600207 confData << "map passwd uid "
208 << ConfigIface::userNameAttribute() << "\n";
209 confData << "map passwd gidNumber "
210 << ConfigIface::groupNameAttribute() << "\n";
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500211 }
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500212 try
213 {
214 std::fstream stream(configFilePath.c_str(), std::fstream::out);
Ratan Gupta9891f2f2018-10-06 12:07:35 +0530215 // remove the read permission from others if password is being written.
216 // nslcd forces this behaviour.
217 auto permission = fs::perms::owner_read | fs::perms::owner_write |
218 fs::perms::group_read;
219 if (isPwdTobeWritten)
220 {
221 fs::permissions(configFilePath, permission);
222 }
223 else
224 {
225 fs::permissions(configFilePath,
226 permission | fs::perms::others_read);
227 }
228
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500229 stream << confData.str();
230 stream.flush();
231 stream.close();
232 }
233 catch (const std::exception& e)
234 {
235 log<level::ERR>(e.what());
236 elog<InternalFailure>();
237 }
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500238 return;
239}
240
Ratan Gupta3a1c2742019-03-20 06:49:42 +0530241std::string Config::lDAPBindDNPassword(std::string value)
242{
243 // Don't update the D-bus object, this is just to
244 // facilitate if user wants to change the bind dn password
245 // once d-bus object gets created.
246 lDAPBindPassword = value;
247 try
248 {
Ratan Guptaec117542019-04-25 18:38:29 +0530249 if (enabled())
250 {
251 writeConfig();
252 parent.startOrStopService(nslcdService, enabled());
253 }
Ratan Gupta21e88cb2019-04-12 17:15:52 +0530254 serialize();
Ratan Gupta3a1c2742019-03-20 06:49:42 +0530255 }
256 catch (const InternalFailure& e)
257 {
258 throw;
259 }
260 catch (const std::exception& e)
261 {
262 log<level::ERR>(e.what());
263 elog<InternalFailure>();
264 }
265 return value;
266}
267
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500268std::string Config::lDAPServerURI(std::string value)
269{
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500270 std::string val;
271 try
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500272 {
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500273 if (value == lDAPServerURI())
274 {
275 return value;
276 }
Nagaraju Goruganti59287f02018-10-12 07:00:20 -0500277 if (isValidLDAPURI(value, LDAPSscheme))
Nagaraju Gorugantib26799a2018-09-28 13:12:19 -0500278 {
Nagaraju Goruganti59287f02018-10-12 07:00:20 -0500279 secureLDAP = true;
280 }
281 else if (isValidLDAPURI(value, LDAPscheme))
282 {
283 secureLDAP = false;
Nagaraju Gorugantidb60f582018-11-08 03:14:48 -0600284 }
285 else
286 {
Nagaraju Goruganti59287f02018-10-12 07:00:20 -0500287 log<level::ERR>("bad LDAP Server URI",
288 entry("LDAPSERVERURI=%s", value.c_str()));
289 elog<InvalidArgument>(Argument::ARGUMENT_NAME("lDAPServerURI"),
290 Argument::ARGUMENT_VALUE(value.c_str()));
Nagaraju Gorugantib26799a2018-09-28 13:12:19 -0500291 }
Nagaraju Goruganti3b4d06a2018-11-08 03:13:38 -0600292
293 if (secureLDAP && !fs::exists(tlsCacertFile.c_str()))
294 {
295 log<level::ERR>("LDAP server's CA certificate not provided",
296 entry("TLSCACERTFILE=%s", tlsCacertFile.c_str()));
297 elog<NoCACertificate>();
298 }
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500299 val = ConfigIface::lDAPServerURI(value);
Ratan Guptaec117542019-04-25 18:38:29 +0530300 if (enabled())
301 {
302 writeConfig();
303 parent.startOrStopService(nslcdService, enabled());
304 }
Ratan Gupta21e88cb2019-04-12 17:15:52 +0530305 // save the object.
306 serialize();
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500307 }
308 catch (const InternalFailure& e)
309 {
310 throw;
311 }
Nagaraju Goruganti59287f02018-10-12 07:00:20 -0500312 catch (const InvalidArgument& e)
313 {
314 throw;
315 }
Nagaraju Goruganti3b4d06a2018-11-08 03:13:38 -0600316 catch (const NoCACertificate& e)
317 {
318 throw;
319 }
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500320 catch (const std::exception& e)
321 {
322 log<level::ERR>(e.what());
323 elog<InternalFailure>();
324 }
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500325 return val;
326}
327
328std::string Config::lDAPBindDN(std::string value)
329{
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500330 std::string val;
331 try
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500332 {
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500333 if (value == lDAPBindDN())
334 {
335 return value;
336 }
337
Nagaraju Gorugantib26799a2018-09-28 13:12:19 -0500338 if (value.empty())
339 {
Nagaraju Goruganti59287f02018-10-12 07:00:20 -0500340 log<level::ERR>("Not a valid LDAP BINDDN",
341 entry("LDAPBINDDN=%s", value.c_str()));
Nagaraju Gorugantib26799a2018-09-28 13:12:19 -0500342 elog<InvalidArgument>(Argument::ARGUMENT_NAME("lDAPBindDN"),
343 Argument::ARGUMENT_VALUE(value.c_str()));
344 }
345
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500346 val = ConfigIface::lDAPBindDN(value);
Ratan Guptaec117542019-04-25 18:38:29 +0530347 if (enabled())
348 {
349 writeConfig();
350 parent.startOrStopService(nslcdService, enabled());
351 }
Ratan Gupta21e88cb2019-04-12 17:15:52 +0530352 // save the object.
353 serialize();
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500354 }
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500355 catch (const InternalFailure& e)
356 {
357 throw;
358 }
Nagaraju Gorugantid514e5d2018-11-08 03:07:25 -0600359 catch (const InvalidArgument& e)
360 {
361 throw;
362 }
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500363 catch (const std::exception& e)
364 {
365 log<level::ERR>(e.what());
366 elog<InternalFailure>();
367 }
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500368 return val;
369}
370
371std::string Config::lDAPBaseDN(std::string value)
372{
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500373 std::string val;
374 try
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500375 {
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500376 if (value == lDAPBaseDN())
377 {
378 return value;
379 }
380
Nagaraju Gorugantib26799a2018-09-28 13:12:19 -0500381 if (value.empty())
382 {
Nagaraju Goruganti59287f02018-10-12 07:00:20 -0500383 log<level::ERR>("Not a valid LDAP BASEDN",
384 entry("BASEDN=%s", value.c_str()));
Nagaraju Gorugantib26799a2018-09-28 13:12:19 -0500385 elog<InvalidArgument>(Argument::ARGUMENT_NAME("lDAPBaseDN"),
386 Argument::ARGUMENT_VALUE(value.c_str()));
387 }
388
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500389 val = ConfigIface::lDAPBaseDN(value);
Ratan Guptaec117542019-04-25 18:38:29 +0530390 if (enabled())
391 {
392 writeConfig();
393 parent.startOrStopService(nslcdService, enabled());
394 }
Ratan Gupta21e88cb2019-04-12 17:15:52 +0530395 // save the object.
396 serialize();
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500397 }
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500398 catch (const InternalFailure& e)
399 {
400 throw;
401 }
Nagaraju Gorugantid514e5d2018-11-08 03:07:25 -0600402 catch (const InvalidArgument& e)
403 {
404 throw;
405 }
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500406 catch (const std::exception& e)
407 {
408 log<level::ERR>(e.what());
409 elog<InternalFailure>();
410 }
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500411 return val;
412}
413
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600414ConfigIface::SearchScope Config::lDAPSearchScope(ConfigIface::SearchScope value)
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500415{
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600416 ConfigIface::SearchScope val;
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500417 try
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500418 {
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500419 if (value == lDAPSearchScope())
420 {
421 return value;
422 }
423
424 val = ConfigIface::lDAPSearchScope(value);
Ratan Guptaec117542019-04-25 18:38:29 +0530425 if (enabled())
426 {
427 writeConfig();
428
429 parent.startOrStopService(nslcdService, enabled());
430 }
Ratan Gupta21e88cb2019-04-12 17:15:52 +0530431 // save the object.
432 serialize();
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500433 }
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500434 catch (const InternalFailure& e)
435 {
436 throw;
437 }
438 catch (const std::exception& e)
439 {
440 log<level::ERR>(e.what());
441 elog<InternalFailure>();
442 }
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500443 return val;
444}
445
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600446ConfigIface::Type Config::lDAPType(ConfigIface::Type value)
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500447{
Ratan Gupta27d4c012019-04-12 13:03:35 +0530448 elog<NotAllowed>(NotAllowedArgument::REASON("ReadOnly Property"));
449 return lDAPType();
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500450}
451
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600452bool Config::enabled(bool value)
453{
Ratan Guptac5481d12019-04-12 18:31:05 +0530454 if (value == enabled())
455 {
456 return value;
457 }
458 // Let parent decide that can we enable this config.
459 // It may happen that other config is already enabled,
460 // Current implementation support only one config can
461 // be active at a time.
462 return parent.enableService(*this, value);
463}
464
465bool Config::enableService(bool value)
466{
467 bool isEnable = false;
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600468 try
469 {
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600470 isEnable = EnableIface::enabled(value);
Ratan Guptaec117542019-04-25 18:38:29 +0530471 if (isEnable)
472 {
473 writeConfig();
474 }
Ratan Guptaec117542019-04-25 18:38:29 +0530475 parent.startOrStopService(nslcdService, value);
Ratan Gupta21e88cb2019-04-12 17:15:52 +0530476 serialize();
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600477 }
478 catch (const InternalFailure& e)
479 {
480 throw;
481 }
482 catch (const std::exception& e)
483 {
484 log<level::ERR>(e.what());
485 elog<InternalFailure>();
486 }
487 return isEnable;
488}
489
490std::string Config::userNameAttribute(std::string value)
491{
492 std::string val;
493 try
494 {
495 if (value == userNameAttribute())
496 {
497 return value;
498 }
499
500 val = ConfigIface::userNameAttribute(value);
Ratan Guptaec117542019-04-25 18:38:29 +0530501 if (enabled())
502 {
503 writeConfig();
504
505 parent.startOrStopService(nslcdService, enabled());
506 }
Ratan Gupta21e88cb2019-04-12 17:15:52 +0530507 // save the object.
508 serialize();
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600509 }
510 catch (const InternalFailure& e)
511 {
512 throw;
513 }
514 catch (const std::exception& e)
515 {
516 log<level::ERR>(e.what());
517 elog<InternalFailure>();
518 }
519 return val;
520}
521
522std::string Config::groupNameAttribute(std::string value)
523{
524 std::string val;
525 try
526 {
527 if (value == groupNameAttribute())
528 {
529 return value;
530 }
531
532 val = ConfigIface::groupNameAttribute(value);
Ratan Guptaec117542019-04-25 18:38:29 +0530533 if (enabled())
534 {
535 writeConfig();
536
537 parent.startOrStopService(nslcdService, enabled());
538 }
Ratan Gupta21e88cb2019-04-12 17:15:52 +0530539 // save the object.
540 serialize();
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600541 }
542 catch (const InternalFailure& e)
543 {
544 throw;
545 }
546 catch (const std::exception& e)
547 {
548 log<level::ERR>(e.what());
549 elog<InternalFailure>();
550 }
551 return val;
552}
553
Ratan Gupta21e88cb2019-04-12 17:15:52 +0530554template <class Archive>
555void Config::save(Archive& archive, const std::uint32_t version) const
556{
557 archive(this->enabled());
558 archive(lDAPServerURI());
559 archive(lDAPBindDN());
560 archive(lDAPBaseDN());
561 archive(lDAPSearchScope());
562 archive(lDAPBindPassword);
563 archive(userNameAttribute());
564 archive(groupNameAttribute());
565}
566
567template <class Archive>
568void Config::load(Archive& archive, const std::uint32_t version)
569{
570
571 bool bVal;
572 archive(bVal);
573 EnableIface::enabled(bVal);
574
575 std::string str;
576 archive(str);
577 ConfigIface::lDAPServerURI(str);
578
579 archive(str);
580 ConfigIface::lDAPBindDN(str);
581
582 archive(str);
583 ConfigIface::lDAPBaseDN(str);
584
585 ConfigIface::SearchScope scope;
586 archive(scope);
587 ConfigIface::lDAPSearchScope(scope);
588
589 archive(str);
590 lDAPBindPassword = str;
591
592 archive(str);
593 ConfigIface::userNameAttribute(str);
594
595 archive(str);
596 ConfigIface::groupNameAttribute(str);
597}
598
599void Config::serialize()
600{
601 std::ofstream os(configPersistPath.string(),
602 std::ios::binary | std::ios::out);
603 cereal::BinaryOutputArchive oarchive(os);
604 oarchive(*this);
605 return;
606}
607
608bool Config::deserialize()
609{
610 try
611 {
612 if (fs::exists(configPersistPath))
613 {
614 std::ifstream is(configPersistPath.c_str(),
615 std::ios::in | std::ios::binary);
616 cereal::BinaryInputArchive iarchive(is);
617 iarchive(*this);
618 return true;
619 }
620 return false;
621 }
622 catch (cereal::Exception& e)
623 {
624 log<level::ERR>(e.what());
625 std::error_code ec;
626 fs::remove(configPersistPath, ec);
627 return false;
628 }
629 catch (const fs::filesystem_error& e)
630 {
631 return false;
632 }
633}
634
Ratan Gupta7b04c352019-04-12 21:46:29 +0530635ObjectPath Config::create(std::string groupName, std::string privilege)
636{
637 checkPrivilegeMapper(groupName);
638 checkPrivilegeLevel(privilege);
639
640 entryId++;
641
642 // Object path for the LDAP group privilege mapper entry
643 fs::path mapperObjectPath = objectPath;
644 mapperObjectPath /= "role_map";
645 mapperObjectPath /= std::to_string(entryId);
646
647 fs::path persistPath = parent.dbusPersistentPath;
648 persistPath += mapperObjectPath;
649
650 // Create mapping for LDAP privilege mapper entry
651 auto entry = std::make_unique<LDAPMapperEntry>(
652 bus, mapperObjectPath.string().c_str(), persistPath.string().c_str(),
653 groupName, privilege, *this);
654
655 phosphor::ldap::serialize(*entry, std::move(persistPath));
656
657 PrivilegeMapperList.emplace(entryId, std::move(entry));
658 return mapperObjectPath.string();
659}
660
661void Config::deletePrivilegeMapper(Id id)
662{
663 fs::path mapperObjectPath = objectPath;
664 mapperObjectPath /= "role_map";
665 mapperObjectPath /= std::to_string(id);
666
667 fs::path persistPath = parent.dbusPersistentPath;
668 persistPath += std::move(mapperObjectPath);
669
670 // Delete the persistent representation of the privilege mapper.
671 fs::remove(std::move(persistPath));
672
673 PrivilegeMapperList.erase(id);
674}
675void Config::checkPrivilegeMapper(const std::string& groupName)
676{
677 if (groupName.empty())
678 {
679 log<level::ERR>("Group name is empty");
680 elog<InvalidArgument>(Argument::ARGUMENT_NAME("Group name"),
681 Argument::ARGUMENT_VALUE("Null"));
682 }
683
684 for (const auto& val : PrivilegeMapperList)
685 {
686 if (val.second.get()->groupName() == groupName)
687 {
688 log<level::ERR>("Group name already exists");
689 elog<PrivilegeMappingExists>();
690 }
691 }
692}
693
694void Config::checkPrivilegeLevel(const std::string& privilege)
695{
696 if (privilege.empty())
697 {
698 log<level::ERR>("Privilege level is empty");
699 elog<InvalidArgument>(Argument::ARGUMENT_NAME("Privilege level"),
700 Argument::ARGUMENT_VALUE("Null"));
701 }
702
703 if (std::find(privMgr.begin(), privMgr.end(), privilege) == privMgr.end())
704 {
705 log<level::ERR>("Invalid privilege");
706 elog<InvalidArgument>(Argument::ARGUMENT_NAME("Privilege level"),
707 Argument::ARGUMENT_VALUE(privilege.c_str()));
708 }
709}
710
711void Config::restoreRoleMapping()
712{
713 namespace fs = std::filesystem;
714 fs::path dir = parent.dbusPersistentPath;
715 dir += objectPath;
716 dir /= "role_map";
717
718 if (!fs::exists(dir) || fs::is_empty(dir))
719 {
720 return;
721 }
722
723 for (auto& file : fs::directory_iterator(dir))
724 {
725 std::string id = file.path().filename().c_str();
726 size_t idNum = std::stol(id);
727
728 auto entryPath = objectPath + '/' + "role_map" + '/' + id;
729 auto persistPath = parent.dbusPersistentPath + entryPath;
730 auto entry = std::make_unique<LDAPMapperEntry>(
731 bus, entryPath.c_str(), persistPath.c_str(), *this);
732 if (phosphor::ldap::deserialize(file.path(), *entry))
733 {
734 entry->Interfaces::emit_object_added();
735 PrivilegeMapperList.emplace(idNum, std::move(entry));
736 if (idNum > entryId)
737 {
738 entryId = idNum;
739 }
740 }
741 }
742}
743
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500744} // namespace ldap
745} // namespace phosphor