blob: b602e88b989bc4d6438999c04f69e2c7659aef83 [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 Guptaab4fcb42019-04-29 19:39:51 +053030constexpr auto certObjPath = "/xyz/openbmc_project/certs/client/ldap/1";
31constexpr auto certRootPath = "/xyz/openbmc_project/certs/client/ldap";
manojkiranedaa47fe4e2019-05-23 21:28:33 +053032constexpr auto authObjPath = "/xyz/openbmc_project/certs/authority/ldap";
Ratan Guptaab4fcb42019-04-29 19:39:51 +053033constexpr auto certIface = "xyz.openbmc_project.Certs.Certificate";
34constexpr auto certProperty = "CertificateString";
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -050035
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -050036using namespace phosphor::logging;
37using namespace sdbusplus::xyz::openbmc_project::Common::Error;
Ratan Gupta95a29312019-02-18 20:34:10 +053038namespace fs = std::filesystem;
Ratan Gupta7b04c352019-04-12 21:46:29 +053039
Nagaraju Gorugantib26799a2018-09-28 13:12:19 -050040using Argument = xyz::openbmc_project::Common::InvalidArgument;
Ratan Gupta27d4c012019-04-12 13:03:35 +053041using NotAllowed = sdbusplus::xyz::openbmc_project::Common::Error::NotAllowed;
42using NotAllowedArgument = xyz::openbmc_project::Common::NotAllowed;
Ratan Gupta7b04c352019-04-12 21:46:29 +053043using PrivilegeMappingExists = sdbusplus::xyz::openbmc_project::User::Common::
44 Error::PrivilegeMappingExists;
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -050045
46using Line = std::string;
47using Key = std::string;
48using Val = std::string;
49using ConfigInfo = std::map<Key, Val>;
50
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -050051Config::Config(sdbusplus::bus::bus& bus, const char* path, const char* filePath,
Ratan Gupta22f13f12019-04-29 15:36:40 +053052 const char* caCertFile, const char* certFile, bool secureLDAP,
Nagaraju Goruganti3b4d06a2018-11-08 03:13:38 -060053 std::string lDAPServerURI, std::string lDAPBindDN,
54 std::string lDAPBaseDN, std::string&& lDAPBindDNPassword,
Ratan Guptaaeaf9412019-02-11 04:41:52 -060055 ConfigIface::SearchScope lDAPSearchScope,
56 ConfigIface::Type lDAPType, bool lDAPServiceEnabled,
57 std::string userNameAttr, std::string groupNameAttr,
58 ConfigMgr& parent) :
59 Ifaces(bus, path, true),
Ratan Gupta3a1c2742019-03-20 06:49:42 +053060 secureLDAP(secureLDAP), lDAPBindPassword(std::move(lDAPBindDNPassword)),
Ratan Gupta22f13f12019-04-29 15:36:40 +053061 tlsCacertFile(caCertFile), tlsCertFile(certFile), configFilePath(filePath),
62 objectPath(path), bus(bus), parent(parent),
63 certificateInstalledSignal(
Ratan Guptaab4fcb42019-04-29 19:39:51 +053064 bus, sdbusplus::bus::match::rules::interfacesAdded(certRootPath),
Ratan Gupta22f13f12019-04-29 15:36:40 +053065 std::bind(std::mem_fn(&Config::certificateInstalled), this,
Ratan Guptaab4fcb42019-04-29 19:39:51 +053066 std::placeholders::_1)),
manojkiranedaa47fe4e2019-05-23 21:28:33 +053067
68 cacertificateInstalledSignal(
69 bus, sdbusplus::bus::match::rules::interfacesAdded(authObjPath),
70 std::bind(std::mem_fn(&Config::certificateInstalled), this,
71 std::placeholders::_1)),
72
Ratan Guptaab4fcb42019-04-29 19:39:51 +053073 certificateChangedSignal(
74 bus,
75 sdbusplus::bus::match::rules::propertiesChanged(certObjPath, certIface),
76 std::bind(std::mem_fn(&Config::certificateChanged), this,
Ratan Gupta22f13f12019-04-29 15:36:40 +053077 std::placeholders::_1))
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -050078{
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -050079 ConfigIface::lDAPServerURI(lDAPServerURI);
80 ConfigIface::lDAPBindDN(lDAPBindDN);
81 ConfigIface::lDAPBaseDN(lDAPBaseDN);
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -050082 ConfigIface::lDAPSearchScope(lDAPSearchScope);
83 ConfigIface::lDAPType(lDAPType);
Ratan Guptaaeaf9412019-02-11 04:41:52 -060084 EnableIface::enabled(lDAPServiceEnabled);
85 ConfigIface::userNameAttribute(userNameAttr);
86 ConfigIface::groupNameAttribute(groupNameAttr);
Ratan Gupta21e88cb2019-04-12 17:15:52 +053087 // NOTE: Don't update the bindDN password under ConfigIface
Ratan Guptaec117542019-04-25 18:38:29 +053088 if (enabled())
89 {
90 writeConfig();
91 }
Ratan Gupta21e88cb2019-04-12 17:15:52 +053092 // save the config.
93 configPersistPath = parent.dbusPersistentPath;
94 configPersistPath += objectPath;
95
96 // create the persistent directory
97 fs::create_directories(configPersistPath);
98
99 configPersistPath += "/config";
100
Ratan Gupta21e88cb2019-04-12 17:15:52 +0530101 serialize();
102
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500103 // Emit deferred signal.
104 this->emit_object_added();
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600105 parent.startOrStopService(nslcdService, enabled());
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500106}
107
Ratan Gupta21e88cb2019-04-12 17:15:52 +0530108Config::Config(sdbusplus::bus::bus& bus, const char* path, const char* filePath,
Ratan Guptaab4fcb42019-04-29 19:39:51 +0530109 const char* caCertFile, const char* certFile,
110 ConfigIface::Type lDAPType, ConfigMgr& parent) :
Ratan Gupta21e88cb2019-04-12 17:15:52 +0530111 Ifaces(bus, path, true),
Ravi Tejad5884042019-06-10 02:35:22 -0500112 secureLDAP(false), tlsCacertFile(caCertFile), tlsCertFile(certFile),
113 configFilePath(filePath), objectPath(path), bus(bus), parent(parent),
Ratan Gupta22f13f12019-04-29 15:36:40 +0530114 certificateInstalledSignal(
Ratan Guptaab4fcb42019-04-29 19:39:51 +0530115 bus, sdbusplus::bus::match::rules::interfacesAdded(certRootPath),
Ratan Gupta22f13f12019-04-29 15:36:40 +0530116 std::bind(std::mem_fn(&Config::certificateInstalled), this,
Ratan Guptaab4fcb42019-04-29 19:39:51 +0530117 std::placeholders::_1)),
manojkiranedaa47fe4e2019-05-23 21:28:33 +0530118 cacertificateInstalledSignal(
119 bus, sdbusplus::bus::match::rules::interfacesAdded(authObjPath),
120 std::bind(std::mem_fn(&Config::certificateInstalled), this,
121 std::placeholders::_1)),
Ratan Guptaab4fcb42019-04-29 19:39:51 +0530122 certificateChangedSignal(
123 bus,
124 sdbusplus::bus::match::rules::propertiesChanged(certObjPath, certIface),
125 std::bind(std::mem_fn(&Config::certificateChanged), this,
Ratan Gupta22f13f12019-04-29 15:36:40 +0530126 std::placeholders::_1))
Ratan Gupta21e88cb2019-04-12 17:15:52 +0530127{
128 ConfigIface::lDAPType(lDAPType);
129
130 configPersistPath = parent.dbusPersistentPath;
131 configPersistPath += objectPath;
132
133 // create the persistent directory
134 fs::create_directories(configPersistPath);
135
136 configPersistPath += "/config";
Ratan Gupta21e88cb2019-04-12 17:15:52 +0530137}
138
Ratan Gupta22f13f12019-04-29 15:36:40 +0530139void Config::certificateInstalled(sdbusplus::message::message& msg)
140{
141 try
142 {
143 if (enabled())
144 {
145 writeConfig();
146 }
147 parent.startOrStopService(nslcdService, enabled());
148 }
149 catch (const InternalFailure& e)
150 {
151 throw;
152 }
153 catch (const std::exception& e)
154 {
155 log<level::ERR>(e.what());
156 elog<InternalFailure>();
157 }
158}
159
Ratan Guptaab4fcb42019-04-29 19:39:51 +0530160void Config::certificateChanged(sdbusplus::message::message& msg)
161{
manojkiraneda75b5a6f2019-05-28 16:23:11 +0530162 std::string objectName;
Patrick Williamsfdf09372020-05-13 18:01:45 -0500163 std::map<std::string, std::variant<std::string>> msgData;
manojkiraneda75b5a6f2019-05-28 16:23:11 +0530164 msg.read(objectName, msgData);
165 auto valPropMap = msgData.find(certProperty);
Ratan Guptaab4fcb42019-04-29 19:39:51 +0530166 {
manojkiraneda75b5a6f2019-05-28 16:23:11 +0530167 if (valPropMap != msgData.end())
Ratan Guptaab4fcb42019-04-29 19:39:51 +0530168 {
manojkiraneda75b5a6f2019-05-28 16:23:11 +0530169 try
170 {
171 if (enabled())
172 {
173
174 writeConfig();
175 }
176 parent.startOrStopService(nslcdService, enabled());
177 }
178 catch (const InternalFailure& e)
179 {
180 throw;
181 }
182 catch (const std::exception& e)
183 {
184 log<level::ERR>(e.what());
185 elog<InternalFailure>();
186 }
Ratan Guptaab4fcb42019-04-29 19:39:51 +0530187 }
Ratan Guptaab4fcb42019-04-29 19:39:51 +0530188 }
189}
190
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500191void Config::writeConfig()
192{
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500193 std::stringstream confData;
Ratan Gupta9891f2f2018-10-06 12:07:35 +0530194 auto isPwdTobeWritten = false;
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600195 std::string userNameAttr;
Ratan Gupta9891f2f2018-10-06 12:07:35 +0530196
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500197 confData << "uid root\n";
198 confData << "gid root\n\n";
199 confData << "ldap_version 3\n\n";
200 confData << "timelimit 30\n";
201 confData << "bind_timelimit 30\n";
202 confData << "pagesize 1000\n";
203 confData << "referrals off\n\n";
204 confData << "uri " << lDAPServerURI() << "\n\n";
205 confData << "base " << lDAPBaseDN() << "\n\n";
206 confData << "binddn " << lDAPBindDN() << "\n";
Ratan Gupta3a1c2742019-03-20 06:49:42 +0530207 if (!lDAPBindPassword.empty())
Nagaraju Goruganti15675472018-10-05 07:03:05 -0500208 {
Ratan Gupta3a1c2742019-03-20 06:49:42 +0530209 confData << "bindpw " << lDAPBindPassword << "\n";
Ratan Gupta9891f2f2018-10-06 12:07:35 +0530210 isPwdTobeWritten = true;
Nagaraju Goruganti15675472018-10-05 07:03:05 -0500211 }
212 confData << "\n";
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500213 switch (lDAPSearchScope())
214 {
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600215 case ConfigIface::SearchScope::sub:
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500216 confData << "scope sub\n\n";
217 break;
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600218 case ConfigIface::SearchScope::one:
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500219 confData << "scope one\n\n";
220 break;
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600221 case ConfigIface::SearchScope::base:
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500222 confData << "scope base\n\n";
223 break;
224 }
225 confData << "base passwd " << lDAPBaseDN() << "\n";
226 confData << "base shadow " << lDAPBaseDN() << "\n\n";
Nagaraju Gorugantidb60f582018-11-08 03:14:48 -0600227 if (secureLDAP == true)
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500228 {
229 confData << "ssl on\n";
Nagaraju Goruganti3b4d06a2018-11-08 03:13:38 -0600230 confData << "tls_reqcert hard\n";
Zbigniew Kurzynski5d00cf22019-10-03 12:10:20 +0200231 if (fs::is_directory(tlsCacertFile.c_str()))
232 {
233 confData << "tls_cacertdir " << tlsCacertFile.c_str() << "\n";
234 }
235 else
236 {
237 confData << "tls_cacertfile " << tlsCacertFile.c_str() << "\n";
238 }
Ratan Gupta22f13f12019-04-29 15:36:40 +0530239 if (fs::exists(tlsCertFile.c_str()))
240 {
241 confData << "tls_cert " << tlsCertFile.c_str() << "\n";
242 confData << "tls_key " << tlsCertFile.c_str() << "\n";
243 }
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500244 }
245 else
246 {
Nagaraju Goruganti15675472018-10-05 07:03:05 -0500247 confData << "ssl off\n";
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500248 }
Nagaraju Goruganti15675472018-10-05 07:03:05 -0500249 confData << "\n";
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600250 if (lDAPType() == ConfigIface::Type::ActiveDirectory)
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500251 {
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600252 if (ConfigIface::userNameAttribute().empty())
253 {
254 ConfigIface::userNameAttribute("sAMAccountName");
255 }
256 if (ConfigIface::groupNameAttribute().empty())
257 {
258 ConfigIface::groupNameAttribute("primaryGroupID");
259 }
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500260 confData << "filter passwd (&(objectClass=user)(objectClass=person)"
261 "(!(objectClass=computer)))\n";
262 confData
263 << "filter group (|(objectclass=group)(objectclass=groupofnames) "
264 "(objectclass=groupofuniquenames))\n";
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600265 confData << "map passwd uid "
266 << ConfigIface::userNameAttribute() << "\n";
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500267 confData << "map passwd uidNumber "
268 "objectSid:S-1-5-21-3623811015-3361044348-30300820\n";
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600269 confData << "map passwd gidNumber "
270 << ConfigIface::groupNameAttribute() << "\n";
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500271 confData << "map passwd homeDirectory \"/home/$sAMAccountName\"\n";
272 confData << "map passwd gecos displayName\n";
273 confData << "map passwd loginShell \"/bin/bash\"\n";
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500274 confData << "map group gidNumber "
275 "objectSid:S-1-5-21-3623811015-3361044348-30300820\n";
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600276 confData << "map group cn "
277 << ConfigIface::userNameAttribute() << "\n";
Ravi Teja3a003e22020-08-11 11:13:17 -0500278 confData << "nss_initgroups_ignoreusers ALLLOCAL\n";
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500279 }
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600280 else if (lDAPType() == ConfigIface::Type::OpenLdap)
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500281 {
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600282 if (ConfigIface::userNameAttribute().empty())
283 {
raviteja-bc3f56c52019-04-02 11:09:04 -0500284 ConfigIface::userNameAttribute("cn");
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600285 }
286 if (ConfigIface::groupNameAttribute().empty())
287 {
raviteja-bc3f56c52019-04-02 11:09:04 -0500288 ConfigIface::groupNameAttribute("gidNumber");
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600289 }
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500290 confData << "filter passwd (objectclass=*)\n";
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500291 confData << "map passwd gecos displayName\n";
Nagaraju Goruganti808eda42018-10-10 08:48:12 -0500292 confData << "filter group (objectclass=posixGroup)\n";
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600293 confData << "map passwd uid "
294 << ConfigIface::userNameAttribute() << "\n";
295 confData << "map passwd gidNumber "
296 << ConfigIface::groupNameAttribute() << "\n";
Ravi Teja3a003e22020-08-11 11:13:17 -0500297 confData << "nss_initgroups_ignoreusers ALLLOCAL\n";
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500298 }
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500299 try
300 {
301 std::fstream stream(configFilePath.c_str(), std::fstream::out);
Ratan Gupta9891f2f2018-10-06 12:07:35 +0530302 // remove the read permission from others if password is being written.
303 // nslcd forces this behaviour.
304 auto permission = fs::perms::owner_read | fs::perms::owner_write |
305 fs::perms::group_read;
306 if (isPwdTobeWritten)
307 {
308 fs::permissions(configFilePath, permission);
309 }
310 else
311 {
312 fs::permissions(configFilePath,
313 permission | fs::perms::others_read);
314 }
315
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500316 stream << confData.str();
317 stream.flush();
318 stream.close();
319 }
320 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;
326}
327
Ratan Gupta3a1c2742019-03-20 06:49:42 +0530328std::string Config::lDAPBindDNPassword(std::string value)
329{
330 // Don't update the D-bus object, this is just to
331 // facilitate if user wants to change the bind dn password
332 // once d-bus object gets created.
333 lDAPBindPassword = value;
334 try
335 {
Ratan Guptaec117542019-04-25 18:38:29 +0530336 if (enabled())
337 {
338 writeConfig();
339 parent.startOrStopService(nslcdService, enabled());
340 }
Ratan Gupta21e88cb2019-04-12 17:15:52 +0530341 serialize();
Ratan Gupta3a1c2742019-03-20 06:49:42 +0530342 }
343 catch (const InternalFailure& e)
344 {
345 throw;
346 }
347 catch (const std::exception& e)
348 {
349 log<level::ERR>(e.what());
350 elog<InternalFailure>();
351 }
352 return value;
353}
354
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500355std::string Config::lDAPServerURI(std::string value)
356{
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500357 std::string val;
358 try
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500359 {
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500360 if (value == lDAPServerURI())
361 {
362 return value;
363 }
Nagaraju Goruganti59287f02018-10-12 07:00:20 -0500364 if (isValidLDAPURI(value, LDAPSscheme))
Nagaraju Gorugantib26799a2018-09-28 13:12:19 -0500365 {
Nagaraju Goruganti59287f02018-10-12 07:00:20 -0500366 secureLDAP = true;
367 }
368 else if (isValidLDAPURI(value, LDAPscheme))
369 {
370 secureLDAP = false;
Nagaraju Gorugantidb60f582018-11-08 03:14:48 -0600371 }
372 else
373 {
Nagaraju Goruganti59287f02018-10-12 07:00:20 -0500374 log<level::ERR>("bad LDAP Server URI",
375 entry("LDAPSERVERURI=%s", value.c_str()));
376 elog<InvalidArgument>(Argument::ARGUMENT_NAME("lDAPServerURI"),
377 Argument::ARGUMENT_VALUE(value.c_str()));
Nagaraju Gorugantib26799a2018-09-28 13:12:19 -0500378 }
Nagaraju Goruganti3b4d06a2018-11-08 03:13:38 -0600379
380 if (secureLDAP && !fs::exists(tlsCacertFile.c_str()))
381 {
382 log<level::ERR>("LDAP server's CA certificate not provided",
383 entry("TLSCACERTFILE=%s", tlsCacertFile.c_str()));
384 elog<NoCACertificate>();
385 }
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500386 val = ConfigIface::lDAPServerURI(value);
Ratan Guptaec117542019-04-25 18:38:29 +0530387 if (enabled())
388 {
389 writeConfig();
390 parent.startOrStopService(nslcdService, enabled());
391 }
Ratan Gupta21e88cb2019-04-12 17:15:52 +0530392 // save the object.
393 serialize();
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500394 }
395 catch (const InternalFailure& e)
396 {
397 throw;
398 }
Nagaraju Goruganti59287f02018-10-12 07:00:20 -0500399 catch (const InvalidArgument& e)
400 {
401 throw;
402 }
Nagaraju Goruganti3b4d06a2018-11-08 03:13:38 -0600403 catch (const NoCACertificate& e)
404 {
405 throw;
406 }
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500407 catch (const std::exception& e)
408 {
409 log<level::ERR>(e.what());
410 elog<InternalFailure>();
411 }
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500412 return val;
413}
414
415std::string Config::lDAPBindDN(std::string value)
416{
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500417 std::string val;
418 try
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500419 {
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500420 if (value == lDAPBindDN())
421 {
422 return value;
423 }
424
Nagaraju Gorugantib26799a2018-09-28 13:12:19 -0500425 if (value.empty())
426 {
Nagaraju Goruganti59287f02018-10-12 07:00:20 -0500427 log<level::ERR>("Not a valid LDAP BINDDN",
428 entry("LDAPBINDDN=%s", value.c_str()));
Nagaraju Gorugantib26799a2018-09-28 13:12:19 -0500429 elog<InvalidArgument>(Argument::ARGUMENT_NAME("lDAPBindDN"),
430 Argument::ARGUMENT_VALUE(value.c_str()));
431 }
432
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500433 val = ConfigIface::lDAPBindDN(value);
Ratan Guptaec117542019-04-25 18:38:29 +0530434 if (enabled())
435 {
436 writeConfig();
437 parent.startOrStopService(nslcdService, enabled());
438 }
Ratan Gupta21e88cb2019-04-12 17:15:52 +0530439 // save the object.
440 serialize();
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500441 }
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500442 catch (const InternalFailure& e)
443 {
444 throw;
445 }
Nagaraju Gorugantid514e5d2018-11-08 03:07:25 -0600446 catch (const InvalidArgument& e)
447 {
448 throw;
449 }
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500450 catch (const std::exception& e)
451 {
452 log<level::ERR>(e.what());
453 elog<InternalFailure>();
454 }
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500455 return val;
456}
457
458std::string Config::lDAPBaseDN(std::string value)
459{
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500460 std::string val;
461 try
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500462 {
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500463 if (value == lDAPBaseDN())
464 {
465 return value;
466 }
467
Nagaraju Gorugantib26799a2018-09-28 13:12:19 -0500468 if (value.empty())
469 {
Nagaraju Goruganti59287f02018-10-12 07:00:20 -0500470 log<level::ERR>("Not a valid LDAP BASEDN",
471 entry("BASEDN=%s", value.c_str()));
Nagaraju Gorugantib26799a2018-09-28 13:12:19 -0500472 elog<InvalidArgument>(Argument::ARGUMENT_NAME("lDAPBaseDN"),
473 Argument::ARGUMENT_VALUE(value.c_str()));
474 }
475
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500476 val = ConfigIface::lDAPBaseDN(value);
Ratan Guptaec117542019-04-25 18:38:29 +0530477 if (enabled())
478 {
479 writeConfig();
480 parent.startOrStopService(nslcdService, enabled());
481 }
Ratan Gupta21e88cb2019-04-12 17:15:52 +0530482 // save the object.
483 serialize();
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500484 }
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500485 catch (const InternalFailure& e)
486 {
487 throw;
488 }
Nagaraju Gorugantid514e5d2018-11-08 03:07:25 -0600489 catch (const InvalidArgument& e)
490 {
491 throw;
492 }
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500493 catch (const std::exception& e)
494 {
495 log<level::ERR>(e.what());
496 elog<InternalFailure>();
497 }
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500498 return val;
499}
500
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600501ConfigIface::SearchScope Config::lDAPSearchScope(ConfigIface::SearchScope value)
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500502{
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600503 ConfigIface::SearchScope val;
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500504 try
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500505 {
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500506 if (value == lDAPSearchScope())
507 {
508 return value;
509 }
510
511 val = ConfigIface::lDAPSearchScope(value);
Ratan Guptaec117542019-04-25 18:38:29 +0530512 if (enabled())
513 {
514 writeConfig();
515
516 parent.startOrStopService(nslcdService, enabled());
517 }
Ratan Gupta21e88cb2019-04-12 17:15:52 +0530518 // save the object.
519 serialize();
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500520 }
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500521 catch (const InternalFailure& e)
522 {
523 throw;
524 }
525 catch (const std::exception& e)
526 {
527 log<level::ERR>(e.what());
528 elog<InternalFailure>();
529 }
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500530 return val;
531}
532
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600533ConfigIface::Type Config::lDAPType(ConfigIface::Type value)
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500534{
Ratan Gupta27d4c012019-04-12 13:03:35 +0530535 elog<NotAllowed>(NotAllowedArgument::REASON("ReadOnly Property"));
536 return lDAPType();
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500537}
538
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600539bool Config::enabled(bool value)
540{
Ratan Guptac5481d12019-04-12 18:31:05 +0530541 if (value == enabled())
542 {
543 return value;
544 }
545 // Let parent decide that can we enable this config.
546 // It may happen that other config is already enabled,
547 // Current implementation support only one config can
548 // be active at a time.
549 return parent.enableService(*this, value);
550}
551
552bool Config::enableService(bool value)
553{
554 bool isEnable = false;
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600555 try
556 {
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600557 isEnable = EnableIface::enabled(value);
Ratan Guptaec117542019-04-25 18:38:29 +0530558 if (isEnable)
559 {
560 writeConfig();
561 }
Ratan Guptaec117542019-04-25 18:38:29 +0530562 parent.startOrStopService(nslcdService, value);
Ratan Gupta21e88cb2019-04-12 17:15:52 +0530563 serialize();
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600564 }
565 catch (const InternalFailure& e)
566 {
567 throw;
568 }
569 catch (const std::exception& e)
570 {
571 log<level::ERR>(e.what());
572 elog<InternalFailure>();
573 }
574 return isEnable;
575}
576
577std::string Config::userNameAttribute(std::string value)
578{
579 std::string val;
580 try
581 {
582 if (value == userNameAttribute())
583 {
584 return value;
585 }
586
587 val = ConfigIface::userNameAttribute(value);
Ratan Guptaec117542019-04-25 18:38:29 +0530588 if (enabled())
589 {
590 writeConfig();
591
592 parent.startOrStopService(nslcdService, enabled());
593 }
Ratan Gupta21e88cb2019-04-12 17:15:52 +0530594 // save the object.
595 serialize();
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600596 }
597 catch (const InternalFailure& e)
598 {
599 throw;
600 }
601 catch (const std::exception& e)
602 {
603 log<level::ERR>(e.what());
604 elog<InternalFailure>();
605 }
606 return val;
607}
608
609std::string Config::groupNameAttribute(std::string value)
610{
611 std::string val;
612 try
613 {
614 if (value == groupNameAttribute())
615 {
616 return value;
617 }
618
619 val = ConfigIface::groupNameAttribute(value);
Ratan Guptaec117542019-04-25 18:38:29 +0530620 if (enabled())
621 {
622 writeConfig();
623
624 parent.startOrStopService(nslcdService, enabled());
625 }
Ratan Gupta21e88cb2019-04-12 17:15:52 +0530626 // save the object.
627 serialize();
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600628 }
629 catch (const InternalFailure& e)
630 {
631 throw;
632 }
633 catch (const std::exception& e)
634 {
635 log<level::ERR>(e.what());
636 elog<InternalFailure>();
637 }
638 return val;
639}
640
Ratan Gupta21e88cb2019-04-12 17:15:52 +0530641template <class Archive>
642void Config::save(Archive& archive, const std::uint32_t version) const
643{
644 archive(this->enabled());
645 archive(lDAPServerURI());
646 archive(lDAPBindDN());
647 archive(lDAPBaseDN());
648 archive(lDAPSearchScope());
649 archive(lDAPBindPassword);
650 archive(userNameAttribute());
651 archive(groupNameAttribute());
652}
653
654template <class Archive>
655void Config::load(Archive& archive, const std::uint32_t version)
656{
Ratan Gupta21e88cb2019-04-12 17:15:52 +0530657 bool bVal;
658 archive(bVal);
659 EnableIface::enabled(bVal);
660
661 std::string str;
662 archive(str);
663 ConfigIface::lDAPServerURI(str);
664
665 archive(str);
666 ConfigIface::lDAPBindDN(str);
667
668 archive(str);
669 ConfigIface::lDAPBaseDN(str);
670
671 ConfigIface::SearchScope scope;
672 archive(scope);
673 ConfigIface::lDAPSearchScope(scope);
674
675 archive(str);
676 lDAPBindPassword = str;
677
678 archive(str);
679 ConfigIface::userNameAttribute(str);
680
681 archive(str);
682 ConfigIface::groupNameAttribute(str);
683}
684
685void Config::serialize()
686{
Ravi Teja59dba442019-05-20 09:31:28 -0500687
688 if (!fs::exists(configPersistPath.c_str()))
689 {
690 std::ofstream os(configPersistPath.string(),
691 std::ios::binary | std::ios::out);
692 auto permission = fs::perms::owner_read | fs::perms::owner_write |
693 fs::perms::group_read;
694 fs::permissions(configPersistPath, permission);
695 cereal::BinaryOutputArchive oarchive(os);
696 oarchive(*this);
697 }
698 else
699 {
700 std::ofstream os(configPersistPath.string(),
701 std::ios::binary | std::ios::out);
702 cereal::BinaryOutputArchive oarchive(os);
703 oarchive(*this);
704 }
Ratan Gupta21e88cb2019-04-12 17:15:52 +0530705 return;
706}
707
708bool Config::deserialize()
709{
710 try
711 {
712 if (fs::exists(configPersistPath))
713 {
714 std::ifstream is(configPersistPath.c_str(),
715 std::ios::in | std::ios::binary);
716 cereal::BinaryInputArchive iarchive(is);
717 iarchive(*this);
Ravi Tejad5884042019-06-10 02:35:22 -0500718
719 if (isValidLDAPURI(lDAPServerURI(), LDAPscheme))
720 {
721 secureLDAP = false;
722 }
723 else if (isValidLDAPURI(lDAPServerURI(), LDAPSscheme))
724 {
725 secureLDAP = true;
726 }
Ratan Gupta21e88cb2019-04-12 17:15:52 +0530727 return true;
728 }
729 return false;
730 }
731 catch (cereal::Exception& e)
732 {
733 log<level::ERR>(e.what());
734 std::error_code ec;
735 fs::remove(configPersistPath, ec);
736 return false;
737 }
738 catch (const fs::filesystem_error& e)
739 {
740 return false;
741 }
742}
743
Ratan Gupta7b04c352019-04-12 21:46:29 +0530744ObjectPath Config::create(std::string groupName, std::string privilege)
745{
746 checkPrivilegeMapper(groupName);
747 checkPrivilegeLevel(privilege);
748
749 entryId++;
750
751 // Object path for the LDAP group privilege mapper entry
752 fs::path mapperObjectPath = objectPath;
753 mapperObjectPath /= "role_map";
754 mapperObjectPath /= std::to_string(entryId);
755
756 fs::path persistPath = parent.dbusPersistentPath;
757 persistPath += mapperObjectPath;
758
759 // Create mapping for LDAP privilege mapper entry
760 auto entry = std::make_unique<LDAPMapperEntry>(
761 bus, mapperObjectPath.string().c_str(), persistPath.string().c_str(),
762 groupName, privilege, *this);
763
764 phosphor::ldap::serialize(*entry, std::move(persistPath));
765
766 PrivilegeMapperList.emplace(entryId, std::move(entry));
767 return mapperObjectPath.string();
768}
769
770void Config::deletePrivilegeMapper(Id id)
771{
772 fs::path mapperObjectPath = objectPath;
773 mapperObjectPath /= "role_map";
774 mapperObjectPath /= std::to_string(id);
775
776 fs::path persistPath = parent.dbusPersistentPath;
777 persistPath += std::move(mapperObjectPath);
778
779 // Delete the persistent representation of the privilege mapper.
780 fs::remove(std::move(persistPath));
781
782 PrivilegeMapperList.erase(id);
783}
784void Config::checkPrivilegeMapper(const std::string& groupName)
785{
786 if (groupName.empty())
787 {
788 log<level::ERR>("Group name is empty");
789 elog<InvalidArgument>(Argument::ARGUMENT_NAME("Group name"),
790 Argument::ARGUMENT_VALUE("Null"));
791 }
792
793 for (const auto& val : PrivilegeMapperList)
794 {
795 if (val.second.get()->groupName() == groupName)
796 {
797 log<level::ERR>("Group name already exists");
798 elog<PrivilegeMappingExists>();
799 }
800 }
801}
802
803void Config::checkPrivilegeLevel(const std::string& privilege)
804{
805 if (privilege.empty())
806 {
807 log<level::ERR>("Privilege level is empty");
808 elog<InvalidArgument>(Argument::ARGUMENT_NAME("Privilege level"),
809 Argument::ARGUMENT_VALUE("Null"));
810 }
811
812 if (std::find(privMgr.begin(), privMgr.end(), privilege) == privMgr.end())
813 {
814 log<level::ERR>("Invalid privilege");
815 elog<InvalidArgument>(Argument::ARGUMENT_NAME("Privilege level"),
816 Argument::ARGUMENT_VALUE(privilege.c_str()));
817 }
818}
819
820void Config::restoreRoleMapping()
821{
822 namespace fs = std::filesystem;
823 fs::path dir = parent.dbusPersistentPath;
824 dir += objectPath;
825 dir /= "role_map";
826
827 if (!fs::exists(dir) || fs::is_empty(dir))
828 {
829 return;
830 }
831
832 for (auto& file : fs::directory_iterator(dir))
833 {
834 std::string id = file.path().filename().c_str();
835 size_t idNum = std::stol(id);
836
837 auto entryPath = objectPath + '/' + "role_map" + '/' + id;
838 auto persistPath = parent.dbusPersistentPath + entryPath;
839 auto entry = std::make_unique<LDAPMapperEntry>(
840 bus, entryPath.c_str(), persistPath.c_str(), *this);
841 if (phosphor::ldap::deserialize(file.path(), *entry))
842 {
843 entry->Interfaces::emit_object_added();
844 PrivilegeMapperList.emplace(idNum, std::move(entry));
845 if (idNum > entryId)
846 {
847 entryId = idNum;
848 }
849 }
850 }
851}
852
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500853} // namespace ldap
854} // namespace phosphor