blob: 4f2f85c67a982aaf47497f0d730cbd4bfde836b9 [file] [log] [blame]
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -05001#include "ldap_configuration.hpp"
Ratan Gupta95a29312019-02-18 20:34:10 +05302#include "ldap_serialize.hpp"
Nagaraju Goruganti59287f02018-10-12 07:00:20 -05003#include "utils.hpp"
Ratan Gupta95a29312019-02-18 20:34:10 +05304#include <filesystem>
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -05005#include <fstream>
6#include <sstream>
7
8namespace phosphor
9{
10namespace ldap
11{
12constexpr auto nslcdService = "nslcd.service";
Nagaraju Gorugantidccee2b2018-09-25 08:51:06 -050013constexpr auto nscdService = "nscd.service";
Nagaraju Goruganti59287f02018-10-12 07:00:20 -050014constexpr auto LDAPscheme = "ldap";
15constexpr auto LDAPSscheme = "ldaps";
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -050016
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -050017using namespace phosphor::logging;
18using namespace sdbusplus::xyz::openbmc_project::Common::Error;
Ratan Gupta95a29312019-02-18 20:34:10 +053019namespace fs = std::filesystem;
Nagaraju Gorugantib26799a2018-09-28 13:12:19 -050020using Argument = xyz::openbmc_project::Common::InvalidArgument;
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -050021
22using Line = std::string;
23using Key = std::string;
24using Val = std::string;
25using ConfigInfo = std::map<Key, Val>;
26
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -050027Config::Config(sdbusplus::bus::bus& bus, const char* path, const char* filePath,
Nagaraju Goruganti3b4d06a2018-11-08 03:13:38 -060028 const char* caCertFile, bool secureLDAP,
29 std::string lDAPServerURI, std::string lDAPBindDN,
30 std::string lDAPBaseDN, std::string&& lDAPBindDNPassword,
Ratan Guptaaeaf9412019-02-11 04:41:52 -060031 ConfigIface::SearchScope lDAPSearchScope,
32 ConfigIface::Type lDAPType, bool lDAPServiceEnabled,
33 std::string userNameAttr, std::string groupNameAttr,
34 ConfigMgr& parent) :
35 Ifaces(bus, path, true),
Nagaraju Goruganti3b4d06a2018-11-08 03:13:38 -060036 secureLDAP(secureLDAP), configFilePath(filePath), tlsCacertFile(caCertFile),
Nagaraju Gorugantidb60f582018-11-08 03:14:48 -060037 lDAPBindDNPassword(std::move(lDAPBindDNPassword)), bus(bus), parent(parent)
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -050038{
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -050039 ConfigIface::lDAPServerURI(lDAPServerURI);
40 ConfigIface::lDAPBindDN(lDAPBindDN);
41 ConfigIface::lDAPBaseDN(lDAPBaseDN);
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -050042 ConfigIface::lDAPSearchScope(lDAPSearchScope);
43 ConfigIface::lDAPType(lDAPType);
Ratan Guptaaeaf9412019-02-11 04:41:52 -060044 EnableIface::enabled(lDAPServiceEnabled);
45 ConfigIface::userNameAttribute(userNameAttr);
46 ConfigIface::groupNameAttribute(groupNameAttr);
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -050047 writeConfig();
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -050048 // Emit deferred signal.
49 this->emit_object_added();
Ratan Guptaaeaf9412019-02-11 04:41:52 -060050 parent.startOrStopService(nslcdService, enabled());
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -050051}
52
Nagaraju Goruganti24194bd2018-09-18 09:55:09 -050053void Config::delete_()
54{
55 parent.deleteObject();
Nagaraju Gorugantidccee2b2018-09-25 08:51:06 -050056 try
57 {
Nagaraju Gorugantid514e5d2018-11-08 03:07:25 -060058 fs::path configDir = fs::path(configFilePath.c_str()).parent_path();
59
60 fs::copy_file(configDir / defaultNslcdFile, LDAP_CONFIG_FILE,
Nagaraju Gorugantidccee2b2018-09-25 08:51:06 -050061 fs::copy_options::overwrite_existing);
Nagaraju Gorugantidccee2b2018-09-25 08:51:06 -050062 }
63 catch (const std::exception& e)
64 {
65 log<level::ERR>("Failed to rename Config Files while deleting Object",
66 entry("ERR=%s", e.what()));
67 elog<InternalFailure>();
68 }
69
70 parent.restartService(nscdService);
71 parent.stopService(nslcdService);
Nagaraju Goruganti24194bd2018-09-18 09:55:09 -050072}
73
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -050074void Config::writeConfig()
75{
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -050076 std::stringstream confData;
Ratan Gupta9891f2f2018-10-06 12:07:35 +053077 auto isPwdTobeWritten = false;
Ratan Guptaaeaf9412019-02-11 04:41:52 -060078 std::string userNameAttr;
Ratan Gupta9891f2f2018-10-06 12:07:35 +053079
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -050080 confData << "uid root\n";
81 confData << "gid root\n\n";
82 confData << "ldap_version 3\n\n";
83 confData << "timelimit 30\n";
84 confData << "bind_timelimit 30\n";
85 confData << "pagesize 1000\n";
86 confData << "referrals off\n\n";
87 confData << "uri " << lDAPServerURI() << "\n\n";
88 confData << "base " << lDAPBaseDN() << "\n\n";
89 confData << "binddn " << lDAPBindDN() << "\n";
Nagaraju Gorugantidb60f582018-11-08 03:14:48 -060090 if (!lDAPBindDNPassword.empty())
Nagaraju Goruganti15675472018-10-05 07:03:05 -050091 {
Nagaraju Gorugantidb60f582018-11-08 03:14:48 -060092 confData << "bindpw " << lDAPBindDNPassword << "\n";
Ratan Gupta9891f2f2018-10-06 12:07:35 +053093 isPwdTobeWritten = true;
Nagaraju Goruganti15675472018-10-05 07:03:05 -050094 }
95 confData << "\n";
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -050096 switch (lDAPSearchScope())
97 {
Ratan Guptaaeaf9412019-02-11 04:41:52 -060098 case ConfigIface::SearchScope::sub:
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -050099 confData << "scope sub\n\n";
100 break;
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600101 case ConfigIface::SearchScope::one:
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500102 confData << "scope one\n\n";
103 break;
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600104 case ConfigIface::SearchScope::base:
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500105 confData << "scope base\n\n";
106 break;
107 }
108 confData << "base passwd " << lDAPBaseDN() << "\n";
109 confData << "base shadow " << lDAPBaseDN() << "\n\n";
Nagaraju Gorugantidb60f582018-11-08 03:14:48 -0600110 if (secureLDAP == true)
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500111 {
112 confData << "ssl on\n";
Nagaraju Goruganti3b4d06a2018-11-08 03:13:38 -0600113 confData << "tls_reqcert hard\n";
114 confData << "tls_cacertFile " << tlsCacertFile.c_str() << "\n";
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500115 }
116 else
117 {
Nagaraju Goruganti15675472018-10-05 07:03:05 -0500118 confData << "ssl off\n";
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500119 }
Nagaraju Goruganti15675472018-10-05 07:03:05 -0500120 confData << "\n";
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600121 if (lDAPType() == ConfigIface::Type::ActiveDirectory)
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500122 {
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600123 if (ConfigIface::userNameAttribute().empty())
124 {
125 ConfigIface::userNameAttribute("sAMAccountName");
126 }
127 if (ConfigIface::groupNameAttribute().empty())
128 {
129 ConfigIface::groupNameAttribute("primaryGroupID");
130 }
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500131 confData << "filter passwd (&(objectClass=user)(objectClass=person)"
132 "(!(objectClass=computer)))\n";
133 confData
134 << "filter group (|(objectclass=group)(objectclass=groupofnames) "
135 "(objectclass=groupofuniquenames))\n";
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600136 confData << "map passwd uid "
137 << ConfigIface::userNameAttribute() << "\n";
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500138 confData << "map passwd uidNumber "
139 "objectSid:S-1-5-21-3623811015-3361044348-30300820\n";
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600140 confData << "map passwd gidNumber "
141 << ConfigIface::groupNameAttribute() << "\n";
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500142 confData << "map passwd homeDirectory \"/home/$sAMAccountName\"\n";
143 confData << "map passwd gecos displayName\n";
144 confData << "map passwd loginShell \"/bin/bash\"\n";
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500145 confData << "map group gidNumber "
146 "objectSid:S-1-5-21-3623811015-3361044348-30300820\n";
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600147 confData << "map group cn "
148 << ConfigIface::userNameAttribute() << "\n";
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500149 }
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600150 else if (lDAPType() == ConfigIface::Type::OpenLdap)
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500151 {
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600152 if (ConfigIface::userNameAttribute().empty())
153 {
154 ConfigIface::userNameAttribute("uid");
155 }
156 if (ConfigIface::groupNameAttribute().empty())
157 {
158 ConfigIface::groupNameAttribute("gid");
159 }
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500160 confData << "filter passwd (objectclass=*)\n";
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500161 confData << "map passwd gecos displayName\n";
Nagaraju Goruganti808eda42018-10-10 08:48:12 -0500162 confData << "filter group (objectclass=posixGroup)\n";
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600163 confData << "map passwd uid "
164 << ConfigIface::userNameAttribute() << "\n";
165 confData << "map passwd gidNumber "
166 << ConfigIface::groupNameAttribute() << "\n";
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500167 }
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500168 try
169 {
170 std::fstream stream(configFilePath.c_str(), std::fstream::out);
Ratan Gupta9891f2f2018-10-06 12:07:35 +0530171 // remove the read permission from others if password is being written.
172 // nslcd forces this behaviour.
173 auto permission = fs::perms::owner_read | fs::perms::owner_write |
174 fs::perms::group_read;
175 if (isPwdTobeWritten)
176 {
177 fs::permissions(configFilePath, permission);
178 }
179 else
180 {
181 fs::permissions(configFilePath,
182 permission | fs::perms::others_read);
183 }
184
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500185 stream << confData.str();
186 stream.flush();
187 stream.close();
188 }
189 catch (const std::exception& e)
190 {
191 log<level::ERR>(e.what());
192 elog<InternalFailure>();
193 }
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500194 return;
195}
196
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500197std::string Config::lDAPServerURI(std::string value)
198{
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500199 std::string val;
200 try
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500201 {
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500202 if (value == lDAPServerURI())
203 {
204 return value;
205 }
Nagaraju Goruganti59287f02018-10-12 07:00:20 -0500206 if (isValidLDAPURI(value, LDAPSscheme))
Nagaraju Gorugantib26799a2018-09-28 13:12:19 -0500207 {
Nagaraju Goruganti59287f02018-10-12 07:00:20 -0500208 secureLDAP = true;
209 }
210 else if (isValidLDAPURI(value, LDAPscheme))
211 {
212 secureLDAP = false;
Nagaraju Gorugantidb60f582018-11-08 03:14:48 -0600213 }
214 else
215 {
Nagaraju Goruganti59287f02018-10-12 07:00:20 -0500216 log<level::ERR>("bad LDAP Server URI",
217 entry("LDAPSERVERURI=%s", value.c_str()));
218 elog<InvalidArgument>(Argument::ARGUMENT_NAME("lDAPServerURI"),
219 Argument::ARGUMENT_VALUE(value.c_str()));
Nagaraju Gorugantib26799a2018-09-28 13:12:19 -0500220 }
Nagaraju Goruganti3b4d06a2018-11-08 03:13:38 -0600221
222 if (secureLDAP && !fs::exists(tlsCacertFile.c_str()))
223 {
224 log<level::ERR>("LDAP server's CA certificate not provided",
225 entry("TLSCACERTFILE=%s", tlsCacertFile.c_str()));
226 elog<NoCACertificate>();
227 }
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500228 val = ConfigIface::lDAPServerURI(value);
229 writeConfig();
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600230 parent.startOrStopService(nslcdService, enabled());
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500231 }
232 catch (const InternalFailure& e)
233 {
234 throw;
235 }
Nagaraju Goruganti59287f02018-10-12 07:00:20 -0500236 catch (const InvalidArgument& e)
237 {
238 throw;
239 }
Nagaraju Goruganti3b4d06a2018-11-08 03:13:38 -0600240 catch (const NoCACertificate& e)
241 {
242 throw;
243 }
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500244 catch (const std::exception& e)
245 {
246 log<level::ERR>(e.what());
247 elog<InternalFailure>();
248 }
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500249 return val;
250}
251
252std::string Config::lDAPBindDN(std::string value)
253{
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500254 std::string val;
255 try
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500256 {
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500257 if (value == lDAPBindDN())
258 {
259 return value;
260 }
261
Nagaraju Gorugantib26799a2018-09-28 13:12:19 -0500262 if (value.empty())
263 {
Nagaraju Goruganti59287f02018-10-12 07:00:20 -0500264 log<level::ERR>("Not a valid LDAP BINDDN",
265 entry("LDAPBINDDN=%s", value.c_str()));
Nagaraju Gorugantib26799a2018-09-28 13:12:19 -0500266 elog<InvalidArgument>(Argument::ARGUMENT_NAME("lDAPBindDN"),
267 Argument::ARGUMENT_VALUE(value.c_str()));
268 }
269
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500270 val = ConfigIface::lDAPBindDN(value);
271 writeConfig();
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600272 parent.startOrStopService(nslcdService, enabled());
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500273 }
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500274 catch (const InternalFailure& e)
275 {
276 throw;
277 }
Nagaraju Gorugantid514e5d2018-11-08 03:07:25 -0600278 catch (const InvalidArgument& e)
279 {
280 throw;
281 }
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500282 catch (const std::exception& e)
283 {
284 log<level::ERR>(e.what());
285 elog<InternalFailure>();
286 }
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500287 return val;
288}
289
290std::string Config::lDAPBaseDN(std::string value)
291{
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500292 std::string val;
293 try
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500294 {
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500295 if (value == lDAPBaseDN())
296 {
297 return value;
298 }
299
Nagaraju Gorugantib26799a2018-09-28 13:12:19 -0500300 if (value.empty())
301 {
Nagaraju Goruganti59287f02018-10-12 07:00:20 -0500302 log<level::ERR>("Not a valid LDAP BASEDN",
303 entry("BASEDN=%s", value.c_str()));
Nagaraju Gorugantib26799a2018-09-28 13:12:19 -0500304 elog<InvalidArgument>(Argument::ARGUMENT_NAME("lDAPBaseDN"),
305 Argument::ARGUMENT_VALUE(value.c_str()));
306 }
307
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500308 val = ConfigIface::lDAPBaseDN(value);
309 writeConfig();
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600310 parent.startOrStopService(nslcdService, enabled());
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500311 }
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500312 catch (const InternalFailure& e)
313 {
314 throw;
315 }
Nagaraju Gorugantid514e5d2018-11-08 03:07:25 -0600316 catch (const InvalidArgument& 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
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600328ConfigIface::SearchScope Config::lDAPSearchScope(ConfigIface::SearchScope value)
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500329{
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600330 ConfigIface::SearchScope val;
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500331 try
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500332 {
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500333 if (value == lDAPSearchScope())
334 {
335 return value;
336 }
337
338 val = ConfigIface::lDAPSearchScope(value);
339 writeConfig();
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600340 parent.startOrStopService(nslcdService, enabled());
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500341 }
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500342 catch (const InternalFailure& e)
343 {
344 throw;
345 }
346 catch (const std::exception& e)
347 {
348 log<level::ERR>(e.what());
349 elog<InternalFailure>();
350 }
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500351 return val;
352}
353
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600354ConfigIface::Type Config::lDAPType(ConfigIface::Type value)
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500355{
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600356 ConfigIface::Type val;
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500357 try
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500358 {
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500359 if (value == lDAPType())
360 {
361 return value;
362 }
363
364 val = ConfigIface::lDAPType(value);
365 writeConfig();
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600366 parent.startOrStopService(nslcdService, enabled());
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500367 }
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500368 catch (const InternalFailure& e)
369 {
370 throw;
371 }
372 catch (const std::exception& e)
373 {
374 log<level::ERR>(e.what());
375 elog<InternalFailure>();
376 }
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500377 return val;
378}
379
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600380bool Config::enabled(bool value)
381{
382 bool isEnable;
383 try
384 {
385 if (value == enabled())
386 {
387 return value;
388 }
389 isEnable = EnableIface::enabled(value);
Ratan Gupta95a29312019-02-18 20:34:10 +0530390 // save the enabled property.
391 serialize(*this, parent.dbusPersistentPath);
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600392 parent.startOrStopService(nslcdService, value);
393 }
394 catch (const InternalFailure& e)
395 {
396 throw;
397 }
398 catch (const std::exception& e)
399 {
400 log<level::ERR>(e.what());
401 elog<InternalFailure>();
402 }
403 return isEnable;
404}
405
406std::string Config::userNameAttribute(std::string value)
407{
408 std::string val;
409 try
410 {
411 if (value == userNameAttribute())
412 {
413 return value;
414 }
415
416 val = ConfigIface::userNameAttribute(value);
417 writeConfig();
418 parent.startOrStopService(nslcdService, enabled());
419 }
420 catch (const InternalFailure& e)
421 {
422 throw;
423 }
424 catch (const std::exception& e)
425 {
426 log<level::ERR>(e.what());
427 elog<InternalFailure>();
428 }
429 return val;
430}
431
432std::string Config::groupNameAttribute(std::string value)
433{
434 std::string val;
435 try
436 {
437 if (value == groupNameAttribute())
438 {
439 return value;
440 }
441
442 val = ConfigIface::groupNameAttribute(value);
443 writeConfig();
444 parent.startOrStopService(nslcdService, enabled());
445 }
446 catch (const InternalFailure& e)
447 {
448 throw;
449 }
450 catch (const std::exception& e)
451 {
452 log<level::ERR>(e.what());
453 elog<InternalFailure>();
454 }
455 return val;
456}
457
458void ConfigMgr::startOrStopService(const std::string& service, bool start)
459{
460 if (start)
461 {
462 restartService(service);
463 }
464 else
465 {
466 stopService(service);
467 }
468}
469
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500470void ConfigMgr::restartService(const std::string& service)
471{
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500472 try
473 {
474 auto method = bus.new_method_call(SYSTEMD_BUSNAME, SYSTEMD_PATH,
475 SYSTEMD_INTERFACE, "RestartUnit");
476 method.append(service.c_str(), "replace");
477 bus.call_noreply(method);
478 }
479 catch (const sdbusplus::exception::SdBusError& ex)
480 {
Ratan Guptaa9297522019-02-20 15:47:32 +0530481 log<level::ERR>("Failed to restart service",
482 entry("SERVICE=%s", service.c_str()),
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500483 entry("ERR=%s", ex.what()));
484 elog<InternalFailure>();
485 }
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500486}
487
Nagaraju Gorugantidccee2b2018-09-25 08:51:06 -0500488void ConfigMgr::stopService(const std::string& service)
489{
490 try
491 {
492 auto method = bus.new_method_call(SYSTEMD_BUSNAME, SYSTEMD_PATH,
493 SYSTEMD_INTERFACE, "StopUnit");
494 method.append(service.c_str(), "replace");
495 bus.call_noreply(method);
496 }
497 catch (const sdbusplus::exception::SdBusError& ex)
498 {
Ratan Guptaa9297522019-02-20 15:47:32 +0530499 log<level::ERR>("Failed to stop service",
500 entry("SERVICE=%s", service.c_str()),
Nagaraju Gorugantidccee2b2018-09-25 08:51:06 -0500501 entry("ERR=%s", ex.what()));
502 elog<InternalFailure>();
503 }
504}
505
Nagaraju Goruganti24194bd2018-09-18 09:55:09 -0500506void ConfigMgr::deleteObject()
507{
508 configPtr.reset(nullptr);
509}
510
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600511std::string ConfigMgr::createConfig(
512 std::string lDAPServerURI, std::string lDAPBindDN, std::string lDAPBaseDN,
513 std::string lDAPBindDNPassword, CreateIface::SearchScope lDAPSearchScope,
514 CreateIface::Create::Type lDAPType, std::string groupNameAttribute,
515 std::string userNameAttribute)
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500516{
Nagaraju Gorugantidb60f582018-11-08 03:14:48 -0600517 bool secureLDAP = false;
518
Nagaraju Goruganti59287f02018-10-12 07:00:20 -0500519 if (isValidLDAPURI(lDAPServerURI, LDAPSscheme))
Nagaraju Gorugantib26799a2018-09-28 13:12:19 -0500520 {
Nagaraju Gorugantidb60f582018-11-08 03:14:48 -0600521 secureLDAP = true;
522 }
Nagaraju Goruganti59287f02018-10-12 07:00:20 -0500523 else if (isValidLDAPURI(lDAPServerURI, LDAPscheme))
Nagaraju Gorugantidb60f582018-11-08 03:14:48 -0600524 {
525 secureLDAP = false;
526 }
527 else
528 {
529 log<level::ERR>("bad LDAP Server URI",
530 entry("LDAPSERVERURI=%s", lDAPServerURI.c_str()));
Nagaraju Gorugantib26799a2018-09-28 13:12:19 -0500531 elog<InvalidArgument>(Argument::ARGUMENT_NAME("lDAPServerURI"),
532 Argument::ARGUMENT_VALUE(lDAPServerURI.c_str()));
533 }
534
Nagaraju Goruganti3b4d06a2018-11-08 03:13:38 -0600535 if (secureLDAP && !fs::exists(tlsCacertFile.c_str()))
536 {
537 log<level::ERR>("LDAP server's CA certificate not provided",
538 entry("TLSCACERTFILE=%s", tlsCacertFile.c_str()));
539 elog<NoCACertificate>();
540 }
541
Nagaraju Gorugantib26799a2018-09-28 13:12:19 -0500542 if (lDAPBindDN.empty())
543 {
Nagaraju Goruganti59287f02018-10-12 07:00:20 -0500544 log<level::ERR>("Not a valid LDAP BINDDN",
545 entry("LDAPBINDDN=%s", lDAPBindDN.c_str()));
Nagaraju Gorugantib26799a2018-09-28 13:12:19 -0500546 elog<InvalidArgument>(Argument::ARGUMENT_NAME("LDAPBindDN"),
547 Argument::ARGUMENT_VALUE(lDAPBindDN.c_str()));
548 }
549
550 if (lDAPBaseDN.empty())
551 {
Nagaraju Goruganti59287f02018-10-12 07:00:20 -0500552 log<level::ERR>("Not a valid LDAP BASEDN",
553 entry("LDAPBASEDN=%s", lDAPBaseDN.c_str()));
Nagaraju Gorugantib26799a2018-09-28 13:12:19 -0500554 elog<InvalidArgument>(Argument::ARGUMENT_NAME("LDAPBaseDN"),
555 Argument::ARGUMENT_VALUE(lDAPBaseDN.c_str()));
556 }
557
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500558 // With current implementation we support only one LDAP server.
Nagaraju Goruganti24194bd2018-09-18 09:55:09 -0500559 deleteObject();
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500560
561 auto objPath = std::string(LDAP_CONFIG_DBUS_OBJ_PATH);
562 configPtr = std::make_unique<Config>(
Nagaraju Goruganti3b4d06a2018-11-08 03:13:38 -0600563 bus, objPath.c_str(), configFilePath.c_str(), tlsCacertFile.c_str(),
564 secureLDAP, lDAPServerURI, lDAPBindDN, lDAPBaseDN,
565 std::move(lDAPBindDNPassword),
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600566 static_cast<ConfigIface::SearchScope>(lDAPSearchScope),
567 static_cast<ConfigIface::Type>(lDAPType), false, groupNameAttribute,
568 userNameAttribute, *this);
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500569
Nagaraju Gorugantidccee2b2018-09-25 08:51:06 -0500570 restartService(nscdService);
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500571 return objPath;
572}
573
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500574void ConfigMgr::restore(const char* filePath)
575{
576 if (!fs::exists(filePath))
577 {
578 log<level::ERR>("Config file doesn't exists",
Nagaraju Gorugantid514e5d2018-11-08 03:07:25 -0600579 entry("LDAP_CONFIG_FILE=%s", configFilePath.c_str()));
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500580 return;
581 }
582
583 ConfigInfo configValues;
584
585 try
586 {
587 std::fstream stream(filePath, std::fstream::in);
588 Line line;
589 // read characters from stream and places them into line
590 while (std::getline(stream, line))
591 {
592 // remove leading and trailing extra spaces
593 auto firstScan = line.find_first_not_of(' ');
594 auto first =
595 (firstScan == std::string::npos ? line.length() : firstScan);
596 auto last = line.find_last_not_of(' ');
597 line = line.substr(first, last - first + 1);
598 // reduce multiple spaces between two words to a single space
599 auto pred = [](char a, char b) {
600 return (a == b && a == ' ') ? true : false;
601 };
602
603 auto lastPos = std::unique(line.begin(), line.end(), pred);
604
605 line.erase(lastPos, line.end());
606
607 // Ignore if line is empty or starts with '#'
608 if (line.empty() || line.at(0) == '#')
609 {
610 continue;
611 }
612
613 Key key;
614 std::istringstream isLine(line);
615 // extract characters from isLine and stores them into
616 // key until the delimitation character ' ' is found.
617 // If the delimiter is found, it is extracted and discarded
618 // the next input operation will begin after it.
619 if (std::getline(isLine, key, ' '))
620 {
621 Val value;
622 // extract characters after delimitation character ' '
623 if (std::getline(isLine, value, ' '))
624 {
625 // skip line if it starts with "base shadow" or
626 // "base passwd" because we would have 3 entries
627 // ("base lDAPBaseDN" , "base passwd lDAPBaseDN" and
628 // "base shadow lDAPBaseDN") for the property "lDAPBaseDN",
629 // one is enough to restore it.
630
631 if ((key == "base") &&
632 (value == "passwd" || value == "shadow"))
633 {
634 continue;
635 }
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600636
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500637 // if config type is AD "map group" entry would be add to
638 // the map configValues. For OpenLdap config file no map
639 // entry would be there.
640 if ((key == "map") && (value == "passwd"))
641 {
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600642 key = key + "_" + value;
643 if (std::getline(isLine, value, ' '))
644 {
645 key += "_" + value;
646 }
647 std::getline(isLine, value, ' ');
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500648 }
649 configValues[key] = value;
650 }
651 }
652 }
653
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600654 CreateIface::SearchScope lDAPSearchScope;
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500655 if (configValues["scope"] == "sub")
656 {
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600657 lDAPSearchScope = CreateIface::SearchScope::sub;
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500658 }
659 else if (configValues["scope"] == "one")
660 {
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600661 lDAPSearchScope = CreateIface::SearchScope::one;
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500662 }
663 else
664 {
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600665 lDAPSearchScope = CreateIface::SearchScope::base;
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500666 }
667
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600668 CreateIface::Type lDAPType;
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500669 // If the file is having a line which starts with "map group"
670 if (configValues["map"] == "group")
671 {
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600672 lDAPType = CreateIface::Type::ActiveDirectory;
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500673 }
674 else
675 {
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600676 lDAPType = CreateIface::Type::OpenLdap;
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500677 }
678
Ratan Guptac9c86a22018-10-18 00:47:01 +0530679 // Don't create the config object if either of the field is empty.
680 if (configValues["uri"] == "" || configValues["binddn"] == "" ||
681 configValues["base"] == "")
682 {
683 log<level::INFO>(
684 "LDAP config parameter value missing",
685 entry("URI=%s", configValues["uri"].c_str()),
686 entry("BASEDN=%s", configValues["base"].c_str()),
687 entry("BINDDN=%s", configValues["binddn"].c_str()));
688 return;
689 }
690
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600691 createConfig(std::move(configValues["uri"]),
692 std::move(configValues["binddn"]),
693 std::move(configValues["base"]),
694 std::move(configValues["bindpw"]), lDAPSearchScope,
695 lDAPType, std::move(configValues["map_passwd_uid"]),
696 std::move(configValues["map_passwd_gidNumber"]));
Ratan Gupta95a29312019-02-18 20:34:10 +0530697
698 // Get the enabled property value from the persistent location
699 if (!deserialize(dbusPersistentPath, *configPtr))
700 {
701 log<level::INFO>(
702 "Deserialization Failed, continue with service disable");
703 }
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500704 }
705 catch (const InvalidArgument& e)
706 {
707 // Don't throw - we don't want to create a D-Bus
708 // object upon finding empty values in config, as
709 // this can be a default config.
710 }
Nagaraju Goruganti3b4d06a2018-11-08 03:13:38 -0600711 catch (const NoCACertificate& e)
712 {
713 // Don't throw - we don't want to create a D-Bus
714 // object upon finding "ssl on" without having tls_cacertFile in place,
715 // as this can be a default config.
716 }
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500717 catch (const InternalFailure& e)
718 {
719 throw;
720 }
721 catch (const std::exception& e)
722 {
723 log<level::ERR>(e.what());
724 elog<InternalFailure>();
725 }
726}
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500727} // namespace ldap
728} // namespace phosphor