blob: 413998a3e579abceeb8bf11dd636e8b330105b5c [file] [log] [blame]
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -05001#include "ldap_configuration.hpp"
Nagaraju Goruganti59287f02018-10-12 07:00:20 -05002#include "utils.hpp"
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -05003#include <experimental/filesystem>
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -05004#include <fstream>
5#include <sstream>
6
7namespace phosphor
8{
9namespace ldap
10{
11constexpr auto nslcdService = "nslcd.service";
Nagaraju Gorugantidccee2b2018-09-25 08:51:06 -050012constexpr auto nscdService = "nscd.service";
Nagaraju Goruganti59287f02018-10-12 07:00:20 -050013constexpr auto LDAPscheme = "ldap";
14constexpr auto LDAPSscheme = "ldaps";
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -050015
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -050016using namespace phosphor::logging;
17using namespace sdbusplus::xyz::openbmc_project::Common::Error;
18namespace fs = std::experimental::filesystem;
Nagaraju Gorugantib26799a2018-09-28 13:12:19 -050019using Argument = xyz::openbmc_project::Common::InvalidArgument;
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -050020
21using Line = std::string;
22using Key = std::string;
23using Val = std::string;
24using ConfigInfo = std::map<Key, Val>;
25
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -050026Config::Config(sdbusplus::bus::bus& bus, const char* path, const char* filePath,
Nagaraju Goruganti3b4d06a2018-11-08 03:13:38 -060027 const char* caCertFile, bool secureLDAP,
28 std::string lDAPServerURI, std::string lDAPBindDN,
29 std::string lDAPBaseDN, std::string&& lDAPBindDNPassword,
Ratan Guptaaeaf9412019-02-11 04:41:52 -060030 ConfigIface::SearchScope lDAPSearchScope,
31 ConfigIface::Type lDAPType, bool lDAPServiceEnabled,
32 std::string userNameAttr, std::string groupNameAttr,
33 ConfigMgr& parent) :
34 Ifaces(bus, path, true),
Nagaraju Goruganti3b4d06a2018-11-08 03:13:38 -060035 secureLDAP(secureLDAP), configFilePath(filePath), tlsCacertFile(caCertFile),
Nagaraju Gorugantidb60f582018-11-08 03:14:48 -060036 lDAPBindDNPassword(std::move(lDAPBindDNPassword)), bus(bus), parent(parent)
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -050037{
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -050038 ConfigIface::lDAPServerURI(lDAPServerURI);
39 ConfigIface::lDAPBindDN(lDAPBindDN);
40 ConfigIface::lDAPBaseDN(lDAPBaseDN);
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -050041 ConfigIface::lDAPSearchScope(lDAPSearchScope);
42 ConfigIface::lDAPType(lDAPType);
Ratan Guptaaeaf9412019-02-11 04:41:52 -060043 EnableIface::enabled(lDAPServiceEnabled);
44 ConfigIface::userNameAttribute(userNameAttr);
45 ConfigIface::groupNameAttribute(groupNameAttr);
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -050046 writeConfig();
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -050047 // Emit deferred signal.
48 this->emit_object_added();
Ratan Guptaaeaf9412019-02-11 04:41:52 -060049 parent.startOrStopService(nslcdService, enabled());
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -050050}
51
Nagaraju Goruganti24194bd2018-09-18 09:55:09 -050052void Config::delete_()
53{
54 parent.deleteObject();
Nagaraju Gorugantidccee2b2018-09-25 08:51:06 -050055 try
56 {
Nagaraju Gorugantid514e5d2018-11-08 03:07:25 -060057 fs::path configDir = fs::path(configFilePath.c_str()).parent_path();
58
59 fs::copy_file(configDir / defaultNslcdFile, LDAP_CONFIG_FILE,
Nagaraju Gorugantidccee2b2018-09-25 08:51:06 -050060 fs::copy_options::overwrite_existing);
Nagaraju Gorugantidccee2b2018-09-25 08:51:06 -050061 }
62 catch (const std::exception& e)
63 {
64 log<level::ERR>("Failed to rename Config Files while deleting Object",
65 entry("ERR=%s", e.what()));
66 elog<InternalFailure>();
67 }
68
69 parent.restartService(nscdService);
70 parent.stopService(nslcdService);
Nagaraju Goruganti24194bd2018-09-18 09:55:09 -050071}
72
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -050073void Config::writeConfig()
74{
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -050075 std::stringstream confData;
Ratan Gupta9891f2f2018-10-06 12:07:35 +053076 auto isPwdTobeWritten = false;
Ratan Guptaaeaf9412019-02-11 04:41:52 -060077 std::string userNameAttr;
Ratan Gupta9891f2f2018-10-06 12:07:35 +053078
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -050079 confData << "uid root\n";
80 confData << "gid root\n\n";
81 confData << "ldap_version 3\n\n";
82 confData << "timelimit 30\n";
83 confData << "bind_timelimit 30\n";
84 confData << "pagesize 1000\n";
85 confData << "referrals off\n\n";
86 confData << "uri " << lDAPServerURI() << "\n\n";
87 confData << "base " << lDAPBaseDN() << "\n\n";
88 confData << "binddn " << lDAPBindDN() << "\n";
Nagaraju Gorugantidb60f582018-11-08 03:14:48 -060089 if (!lDAPBindDNPassword.empty())
Nagaraju Goruganti15675472018-10-05 07:03:05 -050090 {
Nagaraju Gorugantidb60f582018-11-08 03:14:48 -060091 confData << "bindpw " << lDAPBindDNPassword << "\n";
Ratan Gupta9891f2f2018-10-06 12:07:35 +053092 isPwdTobeWritten = true;
Nagaraju Goruganti15675472018-10-05 07:03:05 -050093 }
94 confData << "\n";
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -050095 switch (lDAPSearchScope())
96 {
Ratan Guptaaeaf9412019-02-11 04:41:52 -060097 case ConfigIface::SearchScope::sub:
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -050098 confData << "scope sub\n\n";
99 break;
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600100 case ConfigIface::SearchScope::one:
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500101 confData << "scope one\n\n";
102 break;
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600103 case ConfigIface::SearchScope::base:
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500104 confData << "scope base\n\n";
105 break;
106 }
107 confData << "base passwd " << lDAPBaseDN() << "\n";
108 confData << "base shadow " << lDAPBaseDN() << "\n\n";
Nagaraju Gorugantidb60f582018-11-08 03:14:48 -0600109 if (secureLDAP == true)
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500110 {
111 confData << "ssl on\n";
Nagaraju Goruganti3b4d06a2018-11-08 03:13:38 -0600112 confData << "tls_reqcert hard\n";
113 confData << "tls_cacertFile " << tlsCacertFile.c_str() << "\n";
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500114 }
115 else
116 {
Nagaraju Goruganti15675472018-10-05 07:03:05 -0500117 confData << "ssl off\n";
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500118 }
Nagaraju Goruganti15675472018-10-05 07:03:05 -0500119 confData << "\n";
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600120 if (lDAPType() == ConfigIface::Type::ActiveDirectory)
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500121 {
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600122 if (ConfigIface::userNameAttribute().empty())
123 {
124 ConfigIface::userNameAttribute("sAMAccountName");
125 }
126 if (ConfigIface::groupNameAttribute().empty())
127 {
128 ConfigIface::groupNameAttribute("primaryGroupID");
129 }
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500130 confData << "filter passwd (&(objectClass=user)(objectClass=person)"
131 "(!(objectClass=computer)))\n";
132 confData
133 << "filter group (|(objectclass=group)(objectclass=groupofnames) "
134 "(objectclass=groupofuniquenames))\n";
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600135 confData << "map passwd uid "
136 << ConfigIface::userNameAttribute() << "\n";
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500137 confData << "map passwd uidNumber "
138 "objectSid:S-1-5-21-3623811015-3361044348-30300820\n";
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600139 confData << "map passwd gidNumber "
140 << ConfigIface::groupNameAttribute() << "\n";
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500141 confData << "map passwd homeDirectory \"/home/$sAMAccountName\"\n";
142 confData << "map passwd gecos displayName\n";
143 confData << "map passwd loginShell \"/bin/bash\"\n";
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500144 confData << "map group gidNumber "
145 "objectSid:S-1-5-21-3623811015-3361044348-30300820\n";
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600146 confData << "map group cn "
147 << ConfigIface::userNameAttribute() << "\n";
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500148 }
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600149 else if (lDAPType() == ConfigIface::Type::OpenLdap)
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500150 {
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600151 if (ConfigIface::userNameAttribute().empty())
152 {
153 ConfigIface::userNameAttribute("uid");
154 }
155 if (ConfigIface::groupNameAttribute().empty())
156 {
157 ConfigIface::groupNameAttribute("gid");
158 }
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500159 confData << "filter passwd (objectclass=*)\n";
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500160 confData << "map passwd gecos displayName\n";
Nagaraju Goruganti808eda42018-10-10 08:48:12 -0500161 confData << "filter group (objectclass=posixGroup)\n";
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600162 confData << "map passwd uid "
163 << ConfigIface::userNameAttribute() << "\n";
164 confData << "map passwd gidNumber "
165 << ConfigIface::groupNameAttribute() << "\n";
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500166 }
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500167 try
168 {
169 std::fstream stream(configFilePath.c_str(), std::fstream::out);
Ratan Gupta9891f2f2018-10-06 12:07:35 +0530170 // remove the read permission from others if password is being written.
171 // nslcd forces this behaviour.
172 auto permission = fs::perms::owner_read | fs::perms::owner_write |
173 fs::perms::group_read;
174 if (isPwdTobeWritten)
175 {
176 fs::permissions(configFilePath, permission);
177 }
178 else
179 {
180 fs::permissions(configFilePath,
181 permission | fs::perms::others_read);
182 }
183
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500184 stream << confData.str();
185 stream.flush();
186 stream.close();
187 }
188 catch (const std::exception& e)
189 {
190 log<level::ERR>(e.what());
191 elog<InternalFailure>();
192 }
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500193 return;
194}
195
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500196std::string Config::lDAPServerURI(std::string value)
197{
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500198 std::string val;
199 try
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500200 {
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500201 if (value == lDAPServerURI())
202 {
203 return value;
204 }
Nagaraju Goruganti59287f02018-10-12 07:00:20 -0500205 if (isValidLDAPURI(value, LDAPSscheme))
Nagaraju Gorugantib26799a2018-09-28 13:12:19 -0500206 {
Nagaraju Goruganti59287f02018-10-12 07:00:20 -0500207 secureLDAP = true;
208 }
209 else if (isValidLDAPURI(value, LDAPscheme))
210 {
211 secureLDAP = false;
Nagaraju Gorugantidb60f582018-11-08 03:14:48 -0600212 }
213 else
214 {
Nagaraju Goruganti59287f02018-10-12 07:00:20 -0500215 log<level::ERR>("bad LDAP Server URI",
216 entry("LDAPSERVERURI=%s", value.c_str()));
217 elog<InvalidArgument>(Argument::ARGUMENT_NAME("lDAPServerURI"),
218 Argument::ARGUMENT_VALUE(value.c_str()));
Nagaraju Gorugantib26799a2018-09-28 13:12:19 -0500219 }
Nagaraju Goruganti3b4d06a2018-11-08 03:13:38 -0600220
221 if (secureLDAP && !fs::exists(tlsCacertFile.c_str()))
222 {
223 log<level::ERR>("LDAP server's CA certificate not provided",
224 entry("TLSCACERTFILE=%s", tlsCacertFile.c_str()));
225 elog<NoCACertificate>();
226 }
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500227 val = ConfigIface::lDAPServerURI(value);
228 writeConfig();
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600229 parent.startOrStopService(nslcdService, enabled());
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500230 }
231 catch (const InternalFailure& e)
232 {
233 throw;
234 }
Nagaraju Goruganti59287f02018-10-12 07:00:20 -0500235 catch (const InvalidArgument& e)
236 {
237 throw;
238 }
Nagaraju Goruganti3b4d06a2018-11-08 03:13:38 -0600239 catch (const NoCACertificate& e)
240 {
241 throw;
242 }
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500243 catch (const std::exception& e)
244 {
245 log<level::ERR>(e.what());
246 elog<InternalFailure>();
247 }
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500248 return val;
249}
250
251std::string Config::lDAPBindDN(std::string value)
252{
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500253 std::string val;
254 try
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500255 {
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500256 if (value == lDAPBindDN())
257 {
258 return value;
259 }
260
Nagaraju Gorugantib26799a2018-09-28 13:12:19 -0500261 if (value.empty())
262 {
Nagaraju Goruganti59287f02018-10-12 07:00:20 -0500263 log<level::ERR>("Not a valid LDAP BINDDN",
264 entry("LDAPBINDDN=%s", value.c_str()));
Nagaraju Gorugantib26799a2018-09-28 13:12:19 -0500265 elog<InvalidArgument>(Argument::ARGUMENT_NAME("lDAPBindDN"),
266 Argument::ARGUMENT_VALUE(value.c_str()));
267 }
268
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500269 val = ConfigIface::lDAPBindDN(value);
270 writeConfig();
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600271 parent.startOrStopService(nslcdService, enabled());
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500272 }
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500273 catch (const InternalFailure& e)
274 {
275 throw;
276 }
Nagaraju Gorugantid514e5d2018-11-08 03:07:25 -0600277 catch (const InvalidArgument& e)
278 {
279 throw;
280 }
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500281 catch (const std::exception& e)
282 {
283 log<level::ERR>(e.what());
284 elog<InternalFailure>();
285 }
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500286 return val;
287}
288
289std::string Config::lDAPBaseDN(std::string value)
290{
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500291 std::string val;
292 try
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500293 {
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500294 if (value == lDAPBaseDN())
295 {
296 return value;
297 }
298
Nagaraju Gorugantib26799a2018-09-28 13:12:19 -0500299 if (value.empty())
300 {
Nagaraju Goruganti59287f02018-10-12 07:00:20 -0500301 log<level::ERR>("Not a valid LDAP BASEDN",
302 entry("BASEDN=%s", value.c_str()));
Nagaraju Gorugantib26799a2018-09-28 13:12:19 -0500303 elog<InvalidArgument>(Argument::ARGUMENT_NAME("lDAPBaseDN"),
304 Argument::ARGUMENT_VALUE(value.c_str()));
305 }
306
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500307 val = ConfigIface::lDAPBaseDN(value);
308 writeConfig();
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600309 parent.startOrStopService(nslcdService, enabled());
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500310 }
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500311 catch (const InternalFailure& e)
312 {
313 throw;
314 }
Nagaraju Gorugantid514e5d2018-11-08 03:07:25 -0600315 catch (const InvalidArgument& e)
316 {
317 throw;
318 }
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500319 catch (const std::exception& e)
320 {
321 log<level::ERR>(e.what());
322 elog<InternalFailure>();
323 }
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500324 return val;
325}
326
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600327ConfigIface::SearchScope Config::lDAPSearchScope(ConfigIface::SearchScope value)
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500328{
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600329 ConfigIface::SearchScope val;
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500330 try
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500331 {
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500332 if (value == lDAPSearchScope())
333 {
334 return value;
335 }
336
337 val = ConfigIface::lDAPSearchScope(value);
338 writeConfig();
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600339 parent.startOrStopService(nslcdService, enabled());
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500340 }
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500341 catch (const InternalFailure& e)
342 {
343 throw;
344 }
345 catch (const std::exception& e)
346 {
347 log<level::ERR>(e.what());
348 elog<InternalFailure>();
349 }
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500350 return val;
351}
352
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600353ConfigIface::Type Config::lDAPType(ConfigIface::Type value)
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500354{
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600355 ConfigIface::Type val;
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500356 try
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500357 {
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500358 if (value == lDAPType())
359 {
360 return value;
361 }
362
363 val = ConfigIface::lDAPType(value);
364 writeConfig();
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600365 parent.startOrStopService(nslcdService, enabled());
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500366 }
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500367 catch (const InternalFailure& e)
368 {
369 throw;
370 }
371 catch (const std::exception& e)
372 {
373 log<level::ERR>(e.what());
374 elog<InternalFailure>();
375 }
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500376 return val;
377}
378
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600379bool Config::enabled(bool value)
380{
381 bool isEnable;
382 try
383 {
384 if (value == enabled())
385 {
386 return value;
387 }
388 isEnable = EnableIface::enabled(value);
389 parent.startOrStopService(nslcdService, value);
390 }
391 catch (const InternalFailure& e)
392 {
393 throw;
394 }
395 catch (const std::exception& e)
396 {
397 log<level::ERR>(e.what());
398 elog<InternalFailure>();
399 }
400 return isEnable;
401}
402
403std::string Config::userNameAttribute(std::string value)
404{
405 std::string val;
406 try
407 {
408 if (value == userNameAttribute())
409 {
410 return value;
411 }
412
413 val = ConfigIface::userNameAttribute(value);
414 writeConfig();
415 parent.startOrStopService(nslcdService, enabled());
416 }
417 catch (const InternalFailure& e)
418 {
419 throw;
420 }
421 catch (const std::exception& e)
422 {
423 log<level::ERR>(e.what());
424 elog<InternalFailure>();
425 }
426 return val;
427}
428
429std::string Config::groupNameAttribute(std::string value)
430{
431 std::string val;
432 try
433 {
434 if (value == groupNameAttribute())
435 {
436 return value;
437 }
438
439 val = ConfigIface::groupNameAttribute(value);
440 writeConfig();
441 parent.startOrStopService(nslcdService, enabled());
442 }
443 catch (const InternalFailure& e)
444 {
445 throw;
446 }
447 catch (const std::exception& e)
448 {
449 log<level::ERR>(e.what());
450 elog<InternalFailure>();
451 }
452 return val;
453}
454
455void ConfigMgr::startOrStopService(const std::string& service, bool start)
456{
457 if (start)
458 {
459 restartService(service);
460 }
461 else
462 {
463 stopService(service);
464 }
465}
466
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500467void ConfigMgr::restartService(const std::string& service)
468{
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500469 try
470 {
471 auto method = bus.new_method_call(SYSTEMD_BUSNAME, SYSTEMD_PATH,
472 SYSTEMD_INTERFACE, "RestartUnit");
473 method.append(service.c_str(), "replace");
474 bus.call_noreply(method);
475 }
476 catch (const sdbusplus::exception::SdBusError& ex)
477 {
Ratan Guptaa9297522019-02-20 15:47:32 +0530478 log<level::ERR>("Failed to restart service",
479 entry("SERVICE=%s", service.c_str()),
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500480 entry("ERR=%s", ex.what()));
481 elog<InternalFailure>();
482 }
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500483}
484
Nagaraju Gorugantidccee2b2018-09-25 08:51:06 -0500485void ConfigMgr::stopService(const std::string& service)
486{
487 try
488 {
489 auto method = bus.new_method_call(SYSTEMD_BUSNAME, SYSTEMD_PATH,
490 SYSTEMD_INTERFACE, "StopUnit");
491 method.append(service.c_str(), "replace");
492 bus.call_noreply(method);
493 }
494 catch (const sdbusplus::exception::SdBusError& ex)
495 {
Ratan Guptaa9297522019-02-20 15:47:32 +0530496 log<level::ERR>("Failed to stop service",
497 entry("SERVICE=%s", service.c_str()),
Nagaraju Gorugantidccee2b2018-09-25 08:51:06 -0500498 entry("ERR=%s", ex.what()));
499 elog<InternalFailure>();
500 }
501}
502
Nagaraju Goruganti24194bd2018-09-18 09:55:09 -0500503void ConfigMgr::deleteObject()
504{
505 configPtr.reset(nullptr);
506}
507
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600508std::string ConfigMgr::createConfig(
509 std::string lDAPServerURI, std::string lDAPBindDN, std::string lDAPBaseDN,
510 std::string lDAPBindDNPassword, CreateIface::SearchScope lDAPSearchScope,
511 CreateIface::Create::Type lDAPType, std::string groupNameAttribute,
512 std::string userNameAttribute)
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500513{
Nagaraju Gorugantidb60f582018-11-08 03:14:48 -0600514 bool secureLDAP = false;
515
Nagaraju Goruganti59287f02018-10-12 07:00:20 -0500516 if (isValidLDAPURI(lDAPServerURI, LDAPSscheme))
Nagaraju Gorugantib26799a2018-09-28 13:12:19 -0500517 {
Nagaraju Gorugantidb60f582018-11-08 03:14:48 -0600518 secureLDAP = true;
519 }
Nagaraju Goruganti59287f02018-10-12 07:00:20 -0500520 else if (isValidLDAPURI(lDAPServerURI, LDAPscheme))
Nagaraju Gorugantidb60f582018-11-08 03:14:48 -0600521 {
522 secureLDAP = false;
523 }
524 else
525 {
526 log<level::ERR>("bad LDAP Server URI",
527 entry("LDAPSERVERURI=%s", lDAPServerURI.c_str()));
Nagaraju Gorugantib26799a2018-09-28 13:12:19 -0500528 elog<InvalidArgument>(Argument::ARGUMENT_NAME("lDAPServerURI"),
529 Argument::ARGUMENT_VALUE(lDAPServerURI.c_str()));
530 }
531
Nagaraju Goruganti3b4d06a2018-11-08 03:13:38 -0600532 if (secureLDAP && !fs::exists(tlsCacertFile.c_str()))
533 {
534 log<level::ERR>("LDAP server's CA certificate not provided",
535 entry("TLSCACERTFILE=%s", tlsCacertFile.c_str()));
536 elog<NoCACertificate>();
537 }
538
Nagaraju Gorugantib26799a2018-09-28 13:12:19 -0500539 if (lDAPBindDN.empty())
540 {
Nagaraju Goruganti59287f02018-10-12 07:00:20 -0500541 log<level::ERR>("Not a valid LDAP BINDDN",
542 entry("LDAPBINDDN=%s", lDAPBindDN.c_str()));
Nagaraju Gorugantib26799a2018-09-28 13:12:19 -0500543 elog<InvalidArgument>(Argument::ARGUMENT_NAME("LDAPBindDN"),
544 Argument::ARGUMENT_VALUE(lDAPBindDN.c_str()));
545 }
546
547 if (lDAPBaseDN.empty())
548 {
Nagaraju Goruganti59287f02018-10-12 07:00:20 -0500549 log<level::ERR>("Not a valid LDAP BASEDN",
550 entry("LDAPBASEDN=%s", lDAPBaseDN.c_str()));
Nagaraju Gorugantib26799a2018-09-28 13:12:19 -0500551 elog<InvalidArgument>(Argument::ARGUMENT_NAME("LDAPBaseDN"),
552 Argument::ARGUMENT_VALUE(lDAPBaseDN.c_str()));
553 }
554
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500555 // With current implementation we support only one LDAP server.
Nagaraju Goruganti24194bd2018-09-18 09:55:09 -0500556 deleteObject();
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500557
558 auto objPath = std::string(LDAP_CONFIG_DBUS_OBJ_PATH);
559 configPtr = std::make_unique<Config>(
Nagaraju Goruganti3b4d06a2018-11-08 03:13:38 -0600560 bus, objPath.c_str(), configFilePath.c_str(), tlsCacertFile.c_str(),
561 secureLDAP, lDAPServerURI, lDAPBindDN, lDAPBaseDN,
562 std::move(lDAPBindDNPassword),
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600563 static_cast<ConfigIface::SearchScope>(lDAPSearchScope),
564 static_cast<ConfigIface::Type>(lDAPType), false, groupNameAttribute,
565 userNameAttribute, *this);
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500566
Nagaraju Gorugantidccee2b2018-09-25 08:51:06 -0500567 restartService(nscdService);
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500568 return objPath;
569}
570
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500571void ConfigMgr::restore(const char* filePath)
572{
573 if (!fs::exists(filePath))
574 {
575 log<level::ERR>("Config file doesn't exists",
Nagaraju Gorugantid514e5d2018-11-08 03:07:25 -0600576 entry("LDAP_CONFIG_FILE=%s", configFilePath.c_str()));
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500577 return;
578 }
579
580 ConfigInfo configValues;
581
582 try
583 {
584 std::fstream stream(filePath, std::fstream::in);
585 Line line;
586 // read characters from stream and places them into line
587 while (std::getline(stream, line))
588 {
589 // remove leading and trailing extra spaces
590 auto firstScan = line.find_first_not_of(' ');
591 auto first =
592 (firstScan == std::string::npos ? line.length() : firstScan);
593 auto last = line.find_last_not_of(' ');
594 line = line.substr(first, last - first + 1);
595 // reduce multiple spaces between two words to a single space
596 auto pred = [](char a, char b) {
597 return (a == b && a == ' ') ? true : false;
598 };
599
600 auto lastPos = std::unique(line.begin(), line.end(), pred);
601
602 line.erase(lastPos, line.end());
603
604 // Ignore if line is empty or starts with '#'
605 if (line.empty() || line.at(0) == '#')
606 {
607 continue;
608 }
609
610 Key key;
611 std::istringstream isLine(line);
612 // extract characters from isLine and stores them into
613 // key until the delimitation character ' ' is found.
614 // If the delimiter is found, it is extracted and discarded
615 // the next input operation will begin after it.
616 if (std::getline(isLine, key, ' '))
617 {
618 Val value;
619 // extract characters after delimitation character ' '
620 if (std::getline(isLine, value, ' '))
621 {
622 // skip line if it starts with "base shadow" or
623 // "base passwd" because we would have 3 entries
624 // ("base lDAPBaseDN" , "base passwd lDAPBaseDN" and
625 // "base shadow lDAPBaseDN") for the property "lDAPBaseDN",
626 // one is enough to restore it.
627
628 if ((key == "base") &&
629 (value == "passwd" || value == "shadow"))
630 {
631 continue;
632 }
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600633
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500634 // if config type is AD "map group" entry would be add to
635 // the map configValues. For OpenLdap config file no map
636 // entry would be there.
637 if ((key == "map") && (value == "passwd"))
638 {
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600639 key = key + "_" + value;
640 if (std::getline(isLine, value, ' '))
641 {
642 key += "_" + value;
643 }
644 std::getline(isLine, value, ' ');
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500645 }
646 configValues[key] = value;
647 }
648 }
649 }
650
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600651 CreateIface::SearchScope lDAPSearchScope;
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500652 if (configValues["scope"] == "sub")
653 {
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600654 lDAPSearchScope = CreateIface::SearchScope::sub;
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500655 }
656 else if (configValues["scope"] == "one")
657 {
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600658 lDAPSearchScope = CreateIface::SearchScope::one;
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500659 }
660 else
661 {
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600662 lDAPSearchScope = CreateIface::SearchScope::base;
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500663 }
664
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600665 CreateIface::Type lDAPType;
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500666 // If the file is having a line which starts with "map group"
667 if (configValues["map"] == "group")
668 {
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600669 lDAPType = CreateIface::Type::ActiveDirectory;
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500670 }
671 else
672 {
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600673 lDAPType = CreateIface::Type::OpenLdap;
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500674 }
675
Ratan Guptac9c86a22018-10-18 00:47:01 +0530676 // Don't create the config object if either of the field is empty.
677 if (configValues["uri"] == "" || configValues["binddn"] == "" ||
678 configValues["base"] == "")
679 {
680 log<level::INFO>(
681 "LDAP config parameter value missing",
682 entry("URI=%s", configValues["uri"].c_str()),
683 entry("BASEDN=%s", configValues["base"].c_str()),
684 entry("BINDDN=%s", configValues["binddn"].c_str()));
685 return;
686 }
687
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600688 createConfig(std::move(configValues["uri"]),
689 std::move(configValues["binddn"]),
690 std::move(configValues["base"]),
691 std::move(configValues["bindpw"]), lDAPSearchScope,
692 lDAPType, std::move(configValues["map_passwd_uid"]),
693 std::move(configValues["map_passwd_gidNumber"]));
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500694 }
695 catch (const InvalidArgument& e)
696 {
697 // Don't throw - we don't want to create a D-Bus
698 // object upon finding empty values in config, as
699 // this can be a default config.
700 }
Nagaraju Goruganti3b4d06a2018-11-08 03:13:38 -0600701 catch (const NoCACertificate& e)
702 {
703 // Don't throw - we don't want to create a D-Bus
704 // object upon finding "ssl on" without having tls_cacertFile in place,
705 // as this can be a default config.
706 }
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500707 catch (const InternalFailure& e)
708 {
709 throw;
710 }
711 catch (const std::exception& e)
712 {
713 log<level::ERR>(e.what());
714 elog<InternalFailure>();
715 }
716}
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500717} // namespace ldap
718} // namespace phosphor