blob: 1620d1dd0043fbcea31a4d6f9664889e2d7ebf8b [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;
163 std::map<std::string, sdbusplus::message::variant<std::string>> msgData;
164 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";
231 confData << "tls_cacertFile " << tlsCacertFile.c_str() << "\n";
Ratan Gupta22f13f12019-04-29 15:36:40 +0530232 if (fs::exists(tlsCertFile.c_str()))
233 {
234 confData << "tls_cert " << tlsCertFile.c_str() << "\n";
235 confData << "tls_key " << tlsCertFile.c_str() << "\n";
236 }
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500237 }
238 else
239 {
Nagaraju Goruganti15675472018-10-05 07:03:05 -0500240 confData << "ssl off\n";
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500241 }
Nagaraju Goruganti15675472018-10-05 07:03:05 -0500242 confData << "\n";
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600243 if (lDAPType() == ConfigIface::Type::ActiveDirectory)
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500244 {
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600245 if (ConfigIface::userNameAttribute().empty())
246 {
247 ConfigIface::userNameAttribute("sAMAccountName");
248 }
249 if (ConfigIface::groupNameAttribute().empty())
250 {
251 ConfigIface::groupNameAttribute("primaryGroupID");
252 }
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500253 confData << "filter passwd (&(objectClass=user)(objectClass=person)"
254 "(!(objectClass=computer)))\n";
255 confData
256 << "filter group (|(objectclass=group)(objectclass=groupofnames) "
257 "(objectclass=groupofuniquenames))\n";
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600258 confData << "map passwd uid "
259 << ConfigIface::userNameAttribute() << "\n";
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500260 confData << "map passwd uidNumber "
261 "objectSid:S-1-5-21-3623811015-3361044348-30300820\n";
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600262 confData << "map passwd gidNumber "
263 << ConfigIface::groupNameAttribute() << "\n";
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500264 confData << "map passwd homeDirectory \"/home/$sAMAccountName\"\n";
265 confData << "map passwd gecos displayName\n";
266 confData << "map passwd loginShell \"/bin/bash\"\n";
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500267 confData << "map group gidNumber "
268 "objectSid:S-1-5-21-3623811015-3361044348-30300820\n";
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600269 confData << "map group cn "
270 << ConfigIface::userNameAttribute() << "\n";
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500271 }
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600272 else if (lDAPType() == ConfigIface::Type::OpenLdap)
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500273 {
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600274 if (ConfigIface::userNameAttribute().empty())
275 {
raviteja-bc3f56c52019-04-02 11:09:04 -0500276 ConfigIface::userNameAttribute("cn");
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600277 }
278 if (ConfigIface::groupNameAttribute().empty())
279 {
raviteja-bc3f56c52019-04-02 11:09:04 -0500280 ConfigIface::groupNameAttribute("gidNumber");
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600281 }
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500282 confData << "filter passwd (objectclass=*)\n";
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500283 confData << "map passwd gecos displayName\n";
Nagaraju Goruganti808eda42018-10-10 08:48:12 -0500284 confData << "filter group (objectclass=posixGroup)\n";
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600285 confData << "map passwd uid "
286 << ConfigIface::userNameAttribute() << "\n";
287 confData << "map passwd gidNumber "
288 << ConfigIface::groupNameAttribute() << "\n";
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500289 }
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500290 try
291 {
292 std::fstream stream(configFilePath.c_str(), std::fstream::out);
Ratan Gupta9891f2f2018-10-06 12:07:35 +0530293 // remove the read permission from others if password is being written.
294 // nslcd forces this behaviour.
295 auto permission = fs::perms::owner_read | fs::perms::owner_write |
296 fs::perms::group_read;
297 if (isPwdTobeWritten)
298 {
299 fs::permissions(configFilePath, permission);
300 }
301 else
302 {
303 fs::permissions(configFilePath,
304 permission | fs::perms::others_read);
305 }
306
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500307 stream << confData.str();
308 stream.flush();
309 stream.close();
310 }
311 catch (const std::exception& e)
312 {
313 log<level::ERR>(e.what());
314 elog<InternalFailure>();
315 }
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500316 return;
317}
318
Ratan Gupta3a1c2742019-03-20 06:49:42 +0530319std::string Config::lDAPBindDNPassword(std::string value)
320{
321 // Don't update the D-bus object, this is just to
322 // facilitate if user wants to change the bind dn password
323 // once d-bus object gets created.
324 lDAPBindPassword = value;
325 try
326 {
Ratan Guptaec117542019-04-25 18:38:29 +0530327 if (enabled())
328 {
329 writeConfig();
330 parent.startOrStopService(nslcdService, enabled());
331 }
Ratan Gupta21e88cb2019-04-12 17:15:52 +0530332 serialize();
Ratan Gupta3a1c2742019-03-20 06:49:42 +0530333 }
334 catch (const InternalFailure& e)
335 {
336 throw;
337 }
338 catch (const std::exception& e)
339 {
340 log<level::ERR>(e.what());
341 elog<InternalFailure>();
342 }
343 return value;
344}
345
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500346std::string Config::lDAPServerURI(std::string value)
347{
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500348 std::string val;
349 try
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500350 {
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500351 if (value == lDAPServerURI())
352 {
353 return value;
354 }
Nagaraju Goruganti59287f02018-10-12 07:00:20 -0500355 if (isValidLDAPURI(value, LDAPSscheme))
Nagaraju Gorugantib26799a2018-09-28 13:12:19 -0500356 {
Nagaraju Goruganti59287f02018-10-12 07:00:20 -0500357 secureLDAP = true;
358 }
359 else if (isValidLDAPURI(value, LDAPscheme))
360 {
361 secureLDAP = false;
Nagaraju Gorugantidb60f582018-11-08 03:14:48 -0600362 }
363 else
364 {
Nagaraju Goruganti59287f02018-10-12 07:00:20 -0500365 log<level::ERR>("bad LDAP Server URI",
366 entry("LDAPSERVERURI=%s", value.c_str()));
367 elog<InvalidArgument>(Argument::ARGUMENT_NAME("lDAPServerURI"),
368 Argument::ARGUMENT_VALUE(value.c_str()));
Nagaraju Gorugantib26799a2018-09-28 13:12:19 -0500369 }
Nagaraju Goruganti3b4d06a2018-11-08 03:13:38 -0600370
371 if (secureLDAP && !fs::exists(tlsCacertFile.c_str()))
372 {
373 log<level::ERR>("LDAP server's CA certificate not provided",
374 entry("TLSCACERTFILE=%s", tlsCacertFile.c_str()));
375 elog<NoCACertificate>();
376 }
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500377 val = ConfigIface::lDAPServerURI(value);
Ratan Guptaec117542019-04-25 18:38:29 +0530378 if (enabled())
379 {
380 writeConfig();
381 parent.startOrStopService(nslcdService, enabled());
382 }
Ratan Gupta21e88cb2019-04-12 17:15:52 +0530383 // save the object.
384 serialize();
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500385 }
386 catch (const InternalFailure& e)
387 {
388 throw;
389 }
Nagaraju Goruganti59287f02018-10-12 07:00:20 -0500390 catch (const InvalidArgument& e)
391 {
392 throw;
393 }
Nagaraju Goruganti3b4d06a2018-11-08 03:13:38 -0600394 catch (const NoCACertificate& e)
395 {
396 throw;
397 }
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500398 catch (const std::exception& e)
399 {
400 log<level::ERR>(e.what());
401 elog<InternalFailure>();
402 }
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500403 return val;
404}
405
406std::string Config::lDAPBindDN(std::string value)
407{
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500408 std::string val;
409 try
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500410 {
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500411 if (value == lDAPBindDN())
412 {
413 return value;
414 }
415
Nagaraju Gorugantib26799a2018-09-28 13:12:19 -0500416 if (value.empty())
417 {
Nagaraju Goruganti59287f02018-10-12 07:00:20 -0500418 log<level::ERR>("Not a valid LDAP BINDDN",
419 entry("LDAPBINDDN=%s", value.c_str()));
Nagaraju Gorugantib26799a2018-09-28 13:12:19 -0500420 elog<InvalidArgument>(Argument::ARGUMENT_NAME("lDAPBindDN"),
421 Argument::ARGUMENT_VALUE(value.c_str()));
422 }
423
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500424 val = ConfigIface::lDAPBindDN(value);
Ratan Guptaec117542019-04-25 18:38:29 +0530425 if (enabled())
426 {
427 writeConfig();
428 parent.startOrStopService(nslcdService, enabled());
429 }
Ratan Gupta21e88cb2019-04-12 17:15:52 +0530430 // save the object.
431 serialize();
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500432 }
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500433 catch (const InternalFailure& e)
434 {
435 throw;
436 }
Nagaraju Gorugantid514e5d2018-11-08 03:07:25 -0600437 catch (const InvalidArgument& e)
438 {
439 throw;
440 }
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500441 catch (const std::exception& e)
442 {
443 log<level::ERR>(e.what());
444 elog<InternalFailure>();
445 }
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500446 return val;
447}
448
449std::string Config::lDAPBaseDN(std::string value)
450{
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500451 std::string val;
452 try
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500453 {
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500454 if (value == lDAPBaseDN())
455 {
456 return value;
457 }
458
Nagaraju Gorugantib26799a2018-09-28 13:12:19 -0500459 if (value.empty())
460 {
Nagaraju Goruganti59287f02018-10-12 07:00:20 -0500461 log<level::ERR>("Not a valid LDAP BASEDN",
462 entry("BASEDN=%s", value.c_str()));
Nagaraju Gorugantib26799a2018-09-28 13:12:19 -0500463 elog<InvalidArgument>(Argument::ARGUMENT_NAME("lDAPBaseDN"),
464 Argument::ARGUMENT_VALUE(value.c_str()));
465 }
466
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500467 val = ConfigIface::lDAPBaseDN(value);
Ratan Guptaec117542019-04-25 18:38:29 +0530468 if (enabled())
469 {
470 writeConfig();
471 parent.startOrStopService(nslcdService, enabled());
472 }
Ratan Gupta21e88cb2019-04-12 17:15:52 +0530473 // save the object.
474 serialize();
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500475 }
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500476 catch (const InternalFailure& e)
477 {
478 throw;
479 }
Nagaraju Gorugantid514e5d2018-11-08 03:07:25 -0600480 catch (const InvalidArgument& e)
481 {
482 throw;
483 }
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500484 catch (const std::exception& e)
485 {
486 log<level::ERR>(e.what());
487 elog<InternalFailure>();
488 }
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500489 return val;
490}
491
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600492ConfigIface::SearchScope Config::lDAPSearchScope(ConfigIface::SearchScope value)
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500493{
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600494 ConfigIface::SearchScope val;
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500495 try
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500496 {
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500497 if (value == lDAPSearchScope())
498 {
499 return value;
500 }
501
502 val = ConfigIface::lDAPSearchScope(value);
Ratan Guptaec117542019-04-25 18:38:29 +0530503 if (enabled())
504 {
505 writeConfig();
506
507 parent.startOrStopService(nslcdService, enabled());
508 }
Ratan Gupta21e88cb2019-04-12 17:15:52 +0530509 // save the object.
510 serialize();
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500511 }
Nagaraju Gorugantif1940d92018-09-18 05:05:50 -0500512 catch (const InternalFailure& e)
513 {
514 throw;
515 }
516 catch (const std::exception& e)
517 {
518 log<level::ERR>(e.what());
519 elog<InternalFailure>();
520 }
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500521 return val;
522}
523
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600524ConfigIface::Type Config::lDAPType(ConfigIface::Type value)
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500525{
Ratan Gupta27d4c012019-04-12 13:03:35 +0530526 elog<NotAllowed>(NotAllowedArgument::REASON("ReadOnly Property"));
527 return lDAPType();
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500528}
529
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600530bool Config::enabled(bool value)
531{
Ratan Guptac5481d12019-04-12 18:31:05 +0530532 if (value == enabled())
533 {
534 return value;
535 }
536 // Let parent decide that can we enable this config.
537 // It may happen that other config is already enabled,
538 // Current implementation support only one config can
539 // be active at a time.
540 return parent.enableService(*this, value);
541}
542
543bool Config::enableService(bool value)
544{
545 bool isEnable = false;
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600546 try
547 {
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600548 isEnable = EnableIface::enabled(value);
Ratan Guptaec117542019-04-25 18:38:29 +0530549 if (isEnable)
550 {
551 writeConfig();
552 }
Ratan Guptaec117542019-04-25 18:38:29 +0530553 parent.startOrStopService(nslcdService, value);
Ratan Gupta21e88cb2019-04-12 17:15:52 +0530554 serialize();
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600555 }
556 catch (const InternalFailure& e)
557 {
558 throw;
559 }
560 catch (const std::exception& e)
561 {
562 log<level::ERR>(e.what());
563 elog<InternalFailure>();
564 }
565 return isEnable;
566}
567
568std::string Config::userNameAttribute(std::string value)
569{
570 std::string val;
571 try
572 {
573 if (value == userNameAttribute())
574 {
575 return value;
576 }
577
578 val = ConfigIface::userNameAttribute(value);
Ratan Guptaec117542019-04-25 18:38:29 +0530579 if (enabled())
580 {
581 writeConfig();
582
583 parent.startOrStopService(nslcdService, enabled());
584 }
Ratan Gupta21e88cb2019-04-12 17:15:52 +0530585 // save the object.
586 serialize();
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600587 }
588 catch (const InternalFailure& e)
589 {
590 throw;
591 }
592 catch (const std::exception& e)
593 {
594 log<level::ERR>(e.what());
595 elog<InternalFailure>();
596 }
597 return val;
598}
599
600std::string Config::groupNameAttribute(std::string value)
601{
602 std::string val;
603 try
604 {
605 if (value == groupNameAttribute())
606 {
607 return value;
608 }
609
610 val = ConfigIface::groupNameAttribute(value);
Ratan Guptaec117542019-04-25 18:38:29 +0530611 if (enabled())
612 {
613 writeConfig();
614
615 parent.startOrStopService(nslcdService, enabled());
616 }
Ratan Gupta21e88cb2019-04-12 17:15:52 +0530617 // save the object.
618 serialize();
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600619 }
620 catch (const InternalFailure& e)
621 {
622 throw;
623 }
624 catch (const std::exception& e)
625 {
626 log<level::ERR>(e.what());
627 elog<InternalFailure>();
628 }
629 return val;
630}
631
Ratan Gupta21e88cb2019-04-12 17:15:52 +0530632template <class Archive>
633void Config::save(Archive& archive, const std::uint32_t version) const
634{
635 archive(this->enabled());
636 archive(lDAPServerURI());
637 archive(lDAPBindDN());
638 archive(lDAPBaseDN());
639 archive(lDAPSearchScope());
640 archive(lDAPBindPassword);
641 archive(userNameAttribute());
642 archive(groupNameAttribute());
643}
644
645template <class Archive>
646void Config::load(Archive& archive, const std::uint32_t version)
647{
Ratan Gupta21e88cb2019-04-12 17:15:52 +0530648 bool bVal;
649 archive(bVal);
650 EnableIface::enabled(bVal);
651
652 std::string str;
653 archive(str);
654 ConfigIface::lDAPServerURI(str);
655
656 archive(str);
657 ConfigIface::lDAPBindDN(str);
658
659 archive(str);
660 ConfigIface::lDAPBaseDN(str);
661
662 ConfigIface::SearchScope scope;
663 archive(scope);
664 ConfigIface::lDAPSearchScope(scope);
665
666 archive(str);
667 lDAPBindPassword = str;
668
669 archive(str);
670 ConfigIface::userNameAttribute(str);
671
672 archive(str);
673 ConfigIface::groupNameAttribute(str);
674}
675
676void Config::serialize()
677{
Ravi Teja59dba442019-05-20 09:31:28 -0500678
679 if (!fs::exists(configPersistPath.c_str()))
680 {
681 std::ofstream os(configPersistPath.string(),
682 std::ios::binary | std::ios::out);
683 auto permission = fs::perms::owner_read | fs::perms::owner_write |
684 fs::perms::group_read;
685 fs::permissions(configPersistPath, permission);
686 cereal::BinaryOutputArchive oarchive(os);
687 oarchive(*this);
688 }
689 else
690 {
691 std::ofstream os(configPersistPath.string(),
692 std::ios::binary | std::ios::out);
693 cereal::BinaryOutputArchive oarchive(os);
694 oarchive(*this);
695 }
Ratan Gupta21e88cb2019-04-12 17:15:52 +0530696 return;
697}
698
699bool Config::deserialize()
700{
701 try
702 {
703 if (fs::exists(configPersistPath))
704 {
705 std::ifstream is(configPersistPath.c_str(),
706 std::ios::in | std::ios::binary);
707 cereal::BinaryInputArchive iarchive(is);
708 iarchive(*this);
Ravi Tejad5884042019-06-10 02:35:22 -0500709
710 if (isValidLDAPURI(lDAPServerURI(), LDAPscheme))
711 {
712 secureLDAP = false;
713 }
714 else if (isValidLDAPURI(lDAPServerURI(), LDAPSscheme))
715 {
716 secureLDAP = true;
717 }
Ratan Gupta21e88cb2019-04-12 17:15:52 +0530718 return true;
719 }
720 return false;
721 }
722 catch (cereal::Exception& e)
723 {
724 log<level::ERR>(e.what());
725 std::error_code ec;
726 fs::remove(configPersistPath, ec);
727 return false;
728 }
729 catch (const fs::filesystem_error& e)
730 {
731 return false;
732 }
733}
734
Ratan Gupta7b04c352019-04-12 21:46:29 +0530735ObjectPath Config::create(std::string groupName, std::string privilege)
736{
737 checkPrivilegeMapper(groupName);
738 checkPrivilegeLevel(privilege);
739
740 entryId++;
741
742 // Object path for the LDAP group privilege mapper entry
743 fs::path mapperObjectPath = objectPath;
744 mapperObjectPath /= "role_map";
745 mapperObjectPath /= std::to_string(entryId);
746
747 fs::path persistPath = parent.dbusPersistentPath;
748 persistPath += mapperObjectPath;
749
750 // Create mapping for LDAP privilege mapper entry
751 auto entry = std::make_unique<LDAPMapperEntry>(
752 bus, mapperObjectPath.string().c_str(), persistPath.string().c_str(),
753 groupName, privilege, *this);
754
755 phosphor::ldap::serialize(*entry, std::move(persistPath));
756
757 PrivilegeMapperList.emplace(entryId, std::move(entry));
758 return mapperObjectPath.string();
759}
760
761void Config::deletePrivilegeMapper(Id id)
762{
763 fs::path mapperObjectPath = objectPath;
764 mapperObjectPath /= "role_map";
765 mapperObjectPath /= std::to_string(id);
766
767 fs::path persistPath = parent.dbusPersistentPath;
768 persistPath += std::move(mapperObjectPath);
769
770 // Delete the persistent representation of the privilege mapper.
771 fs::remove(std::move(persistPath));
772
773 PrivilegeMapperList.erase(id);
774}
775void Config::checkPrivilegeMapper(const std::string& groupName)
776{
777 if (groupName.empty())
778 {
779 log<level::ERR>("Group name is empty");
780 elog<InvalidArgument>(Argument::ARGUMENT_NAME("Group name"),
781 Argument::ARGUMENT_VALUE("Null"));
782 }
783
784 for (const auto& val : PrivilegeMapperList)
785 {
786 if (val.second.get()->groupName() == groupName)
787 {
788 log<level::ERR>("Group name already exists");
789 elog<PrivilegeMappingExists>();
790 }
791 }
792}
793
794void Config::checkPrivilegeLevel(const std::string& privilege)
795{
796 if (privilege.empty())
797 {
798 log<level::ERR>("Privilege level is empty");
799 elog<InvalidArgument>(Argument::ARGUMENT_NAME("Privilege level"),
800 Argument::ARGUMENT_VALUE("Null"));
801 }
802
803 if (std::find(privMgr.begin(), privMgr.end(), privilege) == privMgr.end())
804 {
805 log<level::ERR>("Invalid privilege");
806 elog<InvalidArgument>(Argument::ARGUMENT_NAME("Privilege level"),
807 Argument::ARGUMENT_VALUE(privilege.c_str()));
808 }
809}
810
811void Config::restoreRoleMapping()
812{
813 namespace fs = std::filesystem;
814 fs::path dir = parent.dbusPersistentPath;
815 dir += objectPath;
816 dir /= "role_map";
817
818 if (!fs::exists(dir) || fs::is_empty(dir))
819 {
820 return;
821 }
822
823 for (auto& file : fs::directory_iterator(dir))
824 {
825 std::string id = file.path().filename().c_str();
826 size_t idNum = std::stol(id);
827
828 auto entryPath = objectPath + '/' + "role_map" + '/' + id;
829 auto persistPath = parent.dbusPersistentPath + entryPath;
830 auto entry = std::make_unique<LDAPMapperEntry>(
831 bus, entryPath.c_str(), persistPath.c_str(), *this);
832 if (phosphor::ldap::deserialize(file.path(), *entry))
833 {
834 entry->Interfaces::emit_object_added();
835 PrivilegeMapperList.emplace(idNum, std::move(entry));
836 if (idNum > entryId)
837 {
838 entryId = idNum;
839 }
840 }
841 }
842}
843
Nagaraju Goruganti997f5e02018-08-30 03:05:11 -0500844} // namespace ldap
845} // namespace phosphor