summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--phosphor-ldap-config/ldap_configuration.cpp210
-rw-r--r--phosphor-ldap-config/ldap_configuration.hpp71
-rw-r--r--test/ldap_config_test.cpp80
-rw-r--r--user_mgr.cpp201
-rw-r--r--user_mgr.hpp57
5 files changed, 526 insertions, 93 deletions
diff --git a/phosphor-ldap-config/ldap_configuration.cpp b/phosphor-ldap-config/ldap_configuration.cpp
index a54db9b..413998a 100644
--- a/phosphor-ldap-config/ldap_configuration.cpp
+++ b/phosphor-ldap-config/ldap_configuration.cpp
@@ -27,9 +27,11 @@ Config::Config(sdbusplus::bus::bus& bus, const char* path, const char* filePath,
const char* caCertFile, bool secureLDAP,
std::string lDAPServerURI, std::string lDAPBindDN,
std::string lDAPBaseDN, std::string&& lDAPBindDNPassword,
- ldap_base::Config::SearchScope lDAPSearchScope,
- ldap_base::Config::Type lDAPType, ConfigMgr& parent) :
- ConfigIface(bus, path, true),
+ ConfigIface::SearchScope lDAPSearchScope,
+ ConfigIface::Type lDAPType, bool lDAPServiceEnabled,
+ std::string userNameAttr, std::string groupNameAttr,
+ ConfigMgr& parent) :
+ Ifaces(bus, path, true),
secureLDAP(secureLDAP), configFilePath(filePath), tlsCacertFile(caCertFile),
lDAPBindDNPassword(std::move(lDAPBindDNPassword)), bus(bus), parent(parent)
{
@@ -38,9 +40,13 @@ Config::Config(sdbusplus::bus::bus& bus, const char* path, const char* filePath,
ConfigIface::lDAPBaseDN(lDAPBaseDN);
ConfigIface::lDAPSearchScope(lDAPSearchScope);
ConfigIface::lDAPType(lDAPType);
+ EnableIface::enabled(lDAPServiceEnabled);
+ ConfigIface::userNameAttribute(userNameAttr);
+ ConfigIface::groupNameAttribute(groupNameAttr);
writeConfig();
// Emit deferred signal.
this->emit_object_added();
+ parent.startOrStopService(nslcdService, enabled());
}
void Config::delete_()
@@ -68,6 +74,7 @@ void Config::writeConfig()
{
std::stringstream confData;
auto isPwdTobeWritten = false;
+ std::string userNameAttr;
confData << "uid root\n";
confData << "gid root\n\n";
@@ -87,13 +94,13 @@ void Config::writeConfig()
confData << "\n";
switch (lDAPSearchScope())
{
- case ldap_base::Config::SearchScope::sub:
+ case ConfigIface::SearchScope::sub:
confData << "scope sub\n\n";
break;
- case ldap_base::Config::SearchScope::one:
+ case ConfigIface::SearchScope::one:
confData << "scope one\n\n";
break;
- case ldap_base::Config::SearchScope::base:
+ case ConfigIface::SearchScope::base:
confData << "scope base\n\n";
break;
}
@@ -110,30 +117,52 @@ void Config::writeConfig()
confData << "ssl off\n";
}
confData << "\n";
- if (lDAPType() == ldap_base::Config::Type::ActiveDirectory)
+ if (lDAPType() == ConfigIface::Type::ActiveDirectory)
{
+ if (ConfigIface::userNameAttribute().empty())
+ {
+ ConfigIface::userNameAttribute("sAMAccountName");
+ }
+ if (ConfigIface::groupNameAttribute().empty())
+ {
+ ConfigIface::groupNameAttribute("primaryGroupID");
+ }
confData << "filter passwd (&(objectClass=user)(objectClass=person)"
"(!(objectClass=computer)))\n";
confData
<< "filter group (|(objectclass=group)(objectclass=groupofnames) "
"(objectclass=groupofuniquenames))\n";
- confData << "map passwd uid sAMAccountName\n";
+ confData << "map passwd uid "
+ << ConfigIface::userNameAttribute() << "\n";
confData << "map passwd uidNumber "
"objectSid:S-1-5-21-3623811015-3361044348-30300820\n";
- confData << "map passwd gidNumber primaryGroupID\n";
+ confData << "map passwd gidNumber "
+ << ConfigIface::groupNameAttribute() << "\n";
confData << "map passwd homeDirectory \"/home/$sAMAccountName\"\n";
confData << "map passwd gecos displayName\n";
confData << "map passwd loginShell \"/bin/bash\"\n";
- confData << "map group gidNumber primaryGroupID\n";
confData << "map group gidNumber "
"objectSid:S-1-5-21-3623811015-3361044348-30300820\n";
- confData << "map group cn sAMAccountName\n";
+ confData << "map group cn "
+ << ConfigIface::userNameAttribute() << "\n";
}
- else if (lDAPType() == ldap_base::Config::Type::OpenLdap)
+ else if (lDAPType() == ConfigIface::Type::OpenLdap)
{
+ if (ConfigIface::userNameAttribute().empty())
+ {
+ ConfigIface::userNameAttribute("uid");
+ }
+ if (ConfigIface::groupNameAttribute().empty())
+ {
+ ConfigIface::groupNameAttribute("gid");
+ }
confData << "filter passwd (objectclass=*)\n";
confData << "map passwd gecos displayName\n";
confData << "filter group (objectclass=posixGroup)\n";
+ confData << "map passwd uid "
+ << ConfigIface::userNameAttribute() << "\n";
+ confData << "map passwd gidNumber "
+ << ConfigIface::groupNameAttribute() << "\n";
}
try
{
@@ -197,7 +226,7 @@ std::string Config::lDAPServerURI(std::string value)
}
val = ConfigIface::lDAPServerURI(value);
writeConfig();
- parent.restartService(nslcdService);
+ parent.startOrStopService(nslcdService, enabled());
}
catch (const InternalFailure& e)
{
@@ -239,7 +268,7 @@ std::string Config::lDAPBindDN(std::string value)
val = ConfigIface::lDAPBindDN(value);
writeConfig();
- parent.restartService(nslcdService);
+ parent.startOrStopService(nslcdService, enabled());
}
catch (const InternalFailure& e)
{
@@ -277,7 +306,7 @@ std::string Config::lDAPBaseDN(std::string value)
val = ConfigIface::lDAPBaseDN(value);
writeConfig();
- parent.restartService(nslcdService);
+ parent.startOrStopService(nslcdService, enabled());
}
catch (const InternalFailure& e)
{
@@ -295,10 +324,9 @@ std::string Config::lDAPBaseDN(std::string value)
return val;
}
-ldap_base::Config::SearchScope
- Config::lDAPSearchScope(ldap_base::Config::SearchScope value)
+ConfigIface::SearchScope Config::lDAPSearchScope(ConfigIface::SearchScope value)
{
- ldap_base::Config::SearchScope val;
+ ConfigIface::SearchScope val;
try
{
if (value == lDAPSearchScope())
@@ -308,7 +336,7 @@ ldap_base::Config::SearchScope
val = ConfigIface::lDAPSearchScope(value);
writeConfig();
- parent.restartService(nslcdService);
+ parent.startOrStopService(nslcdService, enabled());
}
catch (const InternalFailure& e)
{
@@ -322,9 +350,9 @@ ldap_base::Config::SearchScope
return val;
}
-ldap_base::Config::Type Config::lDAPType(ldap_base::Config::Type value)
+ConfigIface::Type Config::lDAPType(ConfigIface::Type value)
{
- ldap_base::Config::Type val;
+ ConfigIface::Type val;
try
{
if (value == lDAPType())
@@ -334,7 +362,83 @@ ldap_base::Config::Type Config::lDAPType(ldap_base::Config::Type value)
val = ConfigIface::lDAPType(value);
writeConfig();
- parent.restartService(nslcdService);
+ parent.startOrStopService(nslcdService, enabled());
+ }
+ catch (const InternalFailure& e)
+ {
+ throw;
+ }
+ catch (const std::exception& e)
+ {
+ log<level::ERR>(e.what());
+ elog<InternalFailure>();
+ }
+ return val;
+}
+
+bool Config::enabled(bool value)
+{
+ bool isEnable;
+ try
+ {
+ if (value == enabled())
+ {
+ return value;
+ }
+ isEnable = EnableIface::enabled(value);
+ parent.startOrStopService(nslcdService, value);
+ }
+ catch (const InternalFailure& e)
+ {
+ throw;
+ }
+ catch (const std::exception& e)
+ {
+ log<level::ERR>(e.what());
+ elog<InternalFailure>();
+ }
+ return isEnable;
+}
+
+std::string Config::userNameAttribute(std::string value)
+{
+ std::string val;
+ try
+ {
+ if (value == userNameAttribute())
+ {
+ return value;
+ }
+
+ val = ConfigIface::userNameAttribute(value);
+ writeConfig();
+ parent.startOrStopService(nslcdService, enabled());
+ }
+ catch (const InternalFailure& e)
+ {
+ throw;
+ }
+ catch (const std::exception& e)
+ {
+ log<level::ERR>(e.what());
+ elog<InternalFailure>();
+ }
+ return val;
+}
+
+std::string Config::groupNameAttribute(std::string value)
+{
+ std::string val;
+ try
+ {
+ if (value == groupNameAttribute())
+ {
+ return value;
+ }
+
+ val = ConfigIface::groupNameAttribute(value);
+ writeConfig();
+ parent.startOrStopService(nslcdService, enabled());
}
catch (const InternalFailure& e)
{
@@ -348,6 +452,18 @@ ldap_base::Config::Type Config::lDAPType(ldap_base::Config::Type value)
return val;
}
+void ConfigMgr::startOrStopService(const std::string& service, bool start)
+{
+ if (start)
+ {
+ restartService(service);
+ }
+ else
+ {
+ stopService(service);
+ }
+}
+
void ConfigMgr::restartService(const std::string& service)
{
try
@@ -389,12 +505,11 @@ void ConfigMgr::deleteObject()
configPtr.reset(nullptr);
}
-std::string
- ConfigMgr::createConfig(std::string lDAPServerURI, std::string lDAPBindDN,
- std::string lDAPBaseDN,
- std::string lDAPBindDNPassword,
- ldap_base::Create::SearchScope lDAPSearchScope,
- ldap_base::Create::Type lDAPType)
+std::string ConfigMgr::createConfig(
+ std::string lDAPServerURI, std::string lDAPBindDN, std::string lDAPBaseDN,
+ std::string lDAPBindDNPassword, CreateIface::SearchScope lDAPSearchScope,
+ CreateIface::Create::Type lDAPType, std::string groupNameAttribute,
+ std::string userNameAttribute)
{
bool secureLDAP = false;
@@ -445,10 +560,10 @@ std::string
bus, objPath.c_str(), configFilePath.c_str(), tlsCacertFile.c_str(),
secureLDAP, lDAPServerURI, lDAPBindDN, lDAPBaseDN,
std::move(lDAPBindDNPassword),
- static_cast<ldap_base::Config::SearchScope>(lDAPSearchScope),
- static_cast<ldap_base::Config::Type>(lDAPType), *this);
+ static_cast<ConfigIface::SearchScope>(lDAPSearchScope),
+ static_cast<ConfigIface::Type>(lDAPType), false, groupNameAttribute,
+ userNameAttribute, *this);
- restartService(nslcdService);
restartService(nscdService);
return objPath;
}
@@ -515,42 +630,47 @@ void ConfigMgr::restore(const char* filePath)
{
continue;
}
- // skip the line if it starts with "map passwd".
+
// if config type is AD "map group" entry would be add to
// the map configValues. For OpenLdap config file no map
// entry would be there.
if ((key == "map") && (value == "passwd"))
{
- continue;
+ key = key + "_" + value;
+ if (std::getline(isLine, value, ' '))
+ {
+ key += "_" + value;
+ }
+ std::getline(isLine, value, ' ');
}
configValues[key] = value;
}
}
}
- ldap_base::Create::SearchScope lDAPSearchScope;
+ CreateIface::SearchScope lDAPSearchScope;
if (configValues["scope"] == "sub")
{
- lDAPSearchScope = ldap_base::Create::SearchScope::sub;
+ lDAPSearchScope = CreateIface::SearchScope::sub;
}
else if (configValues["scope"] == "one")
{
- lDAPSearchScope = ldap_base::Create::SearchScope::one;
+ lDAPSearchScope = CreateIface::SearchScope::one;
}
else
{
- lDAPSearchScope = ldap_base::Create::SearchScope::base;
+ lDAPSearchScope = CreateIface::SearchScope::base;
}
- ldap_base::Create::Type lDAPType;
+ CreateIface::Type lDAPType;
// If the file is having a line which starts with "map group"
if (configValues["map"] == "group")
{
- lDAPType = ldap_base::Create::Type::ActiveDirectory;
+ lDAPType = CreateIface::Type::ActiveDirectory;
}
else
{
- lDAPType = ldap_base::Create::Type::OpenLdap;
+ lDAPType = CreateIface::Type::OpenLdap;
}
// Don't create the config object if either of the field is empty.
@@ -565,10 +685,12 @@ void ConfigMgr::restore(const char* filePath)
return;
}
- createConfig(
- std::move(configValues["uri"]), std::move(configValues["binddn"]),
- std::move(configValues["base"]), std::move(configValues["bindpw"]),
- lDAPSearchScope, lDAPType);
+ createConfig(std::move(configValues["uri"]),
+ std::move(configValues["binddn"]),
+ std::move(configValues["base"]),
+ std::move(configValues["bindpw"]), lDAPSearchScope,
+ lDAPType, std::move(configValues["map_passwd_uid"]),
+ std::move(configValues["map_passwd_gidNumber"]));
}
catch (const InvalidArgument& e)
{
diff --git a/phosphor-ldap-config/ldap_configuration.hpp b/phosphor-ldap-config/ldap_configuration.hpp
index ad2c52a..0d69f08 100644
--- a/phosphor-ldap-config/ldap_configuration.hpp
+++ b/phosphor-ldap-config/ldap_configuration.hpp
@@ -2,6 +2,7 @@
#include "config.h"
#include <xyz/openbmc_project/Object/Delete/server.hpp>
+#include <xyz/openbmc_project/Object/Enable/server.hpp>
#include <xyz/openbmc_project/User/Ldap/Config/server.hpp>
#include <xyz/openbmc_project/User/Ldap/Create/server.hpp>
#include <xyz/openbmc_project/Common/error.hpp>
@@ -21,10 +22,13 @@ static constexpr auto nsSwitchFile = "nsswitch.conf";
using namespace phosphor::logging;
using namespace sdbusplus::xyz::openbmc_project::Common::Error;
-namespace ldap_base = sdbusplus::xyz::openbmc_project::User::Ldap::server;
-using ConfigIface = sdbusplus::server::object::object<
- ldap_base::Config, sdbusplus::xyz::openbmc_project::Object::server::Delete>;
-using CreateIface = sdbusplus::server::object::object<ldap_base::Create>;
+using ConfigIface = sdbusplus::xyz::openbmc_project::User::Ldap::server::Config;
+using EnableIface = sdbusplus::xyz::openbmc_project::Object::server::Enable;
+using DeleteIface = sdbusplus::xyz::openbmc_project::Object::server::Delete;
+using Ifaces =
+ sdbusplus::server::object::object<ConfigIface, EnableIface, DeleteIface>;
+using CreateIface = sdbusplus::server::object::object<
+ sdbusplus::xyz::openbmc_project::User::Ldap::server::Create>;
class ConfigMgr;
@@ -33,7 +37,7 @@ class ConfigMgr;
* @details concrete implementation of xyz.openbmc_project.User.Ldap.Config
* API, in order to provide LDAP configuration.
*/
-class Config : public ConfigIface
+class Config : public Ifaces
{
public:
Config() = delete;
@@ -55,7 +59,14 @@ class Config : public ConfigIface
* @param[in] lDAPBindDNPassword - credentials with which to bind.
* @param[in] lDAPSearchScope - the search scope.
* @param[in] lDAPType - Specifies the LDAP server type which can be AD
- or openLDAP.
+ * or openLDAP.
+ * @param[in] lDAPServiceEnabled - Specifies whether the service would be
+ * enabled or not.
+ * @param[in] groupNameAttribute - Specifies attribute name that contains
+ * the name of the Group in the LDAP server.
+ * @param[in] userNameAttribute - Specifies attribute name that contains
+ * the username in the LDAP server.
+ *
* @param[in] parent - parent of config object.
*/
@@ -63,15 +74,19 @@ class Config : public ConfigIface
const char* caCertFile, bool secureLDAP, std::string lDAPServerURI,
std::string lDAPBindDN, std::string lDAPBaseDN,
std::string&& lDAPBindDNPassword,
- ldap_base::Config::SearchScope lDAPSearchScope,
- ldap_base::Config::Type lDAPType, ConfigMgr& parent);
+ ConfigIface::SearchScope lDAPSearchScope, ConfigIface::Type lDAPType,
+ bool lDAPServiceEnabled, std::string groupNameAttribute,
+ std::string userNameAttribute, ConfigMgr& parent);
+ using ConfigIface::groupNameAttribute;
using ConfigIface::lDAPBaseDN;
using ConfigIface::lDAPBindDN;
using ConfigIface::lDAPSearchScope;
using ConfigIface::lDAPServerURI;
using ConfigIface::lDAPType;
using ConfigIface::setPropertyByName;
+ using ConfigIface::userNameAttribute;
+ using EnableIface::enabled;
/** @brief Update the Server URI property.
* @param[in] value - lDAPServerURI value to be updated.
@@ -95,14 +110,32 @@ class Config : public ConfigIface
* @param[in] value - lDAPSearchScope value to be updated.
* @returns value of changed lDAPSearchScope.
*/
- ldap_base::Config::SearchScope
- lDAPSearchScope(ldap_base::Config::SearchScope value) override;
+ ConfigIface::SearchScope
+ lDAPSearchScope(ConfigIface::SearchScope value) override;
/** @brief Update the LDAP Type property.
* @param[in] value - lDAPType value to be updated.
* @returns value of changed lDAPType.
*/
- ldap_base::Config::Type lDAPType(ldap_base::Config::Type value) override;
+ ConfigIface::Type lDAPType(ConfigIface::Type value) override;
+
+ /** @brief Update the ldapServiceEnabled property.
+ * @param[in] value - ldapServiceEnabled value to be updated.
+ * @returns value of changed ldapServiceEnabled.
+ */
+ bool enabled(bool value) override;
+
+ /** @brief Update the userNameAttribute property.
+ * @param[in] value - userNameAttribute value to be updated.
+ * @returns value of changed userNameAttribute.
+ */
+ std::string userNameAttribute(std::string value) override;
+
+ /** @brief Update the groupNameAttribute property.
+ * @param[in] value - groupNameAttribute value to be updated.
+ * @returns value of changed groupNameAttribute.
+ */
+ std::string groupNameAttribute(std::string value) override;
/** @brief Delete this D-bus object.
*/
@@ -175,13 +208,19 @@ class ConfigMgr : public CreateIface
* @param[in] lDAPSearchScope - the search scope.
* @param[in] lDAPType - Specifies the LDAP server type which can be AD
or openLDAP.
+ * @param[in] groupNameAttribute - Specifies attribute name that contains
+ * the name of the Group in the LDAP server.
+ * @param[in] usernameAttribute - Specifies attribute name that contains
+ * the username in the LDAP server.
* @returns the object path of the D-Bus object created.
*/
std::string createConfig(std::string lDAPServerURI, std::string lDAPBindDN,
std::string lDAPBaseDN,
std::string lDAPBindDNPassword,
- ldap_base::Create::SearchScope lDAPSearchScope,
- ldap_base::Create::Type lDAPType) override;
+ CreateIface::SearchScope lDAPSearchScope,
+ CreateIface::Type lDAPType,
+ std::string groupNameAttribute,
+ std::string userNameAttribute) override;
/** @brief restarts given service
* @param[in] service - Service to be restarted.
@@ -193,6 +232,12 @@ class ConfigMgr : public CreateIface
*/
virtual void stopService(const std::string& service);
+ /** @brief start or stop the service depending on the given value
+ * @param[in] service - Service to be start/stop.
+ * @param[in] value - true to start the service otherwise stop.
+ */
+ virtual void startOrStopService(const std::string& service, bool value);
+
/** @brief delete the config D-Bus object.
*/
void deleteObject();
diff --git a/test/ldap_config_test.cpp b/test/ldap_config_test.cpp
index 819a8cf..0f22b8f 100644
--- a/test/ldap_config_test.cpp
+++ b/test/ldap_config_test.cpp
@@ -93,11 +93,11 @@ TEST_F(TestLDAPConfig, testCreate)
tlsCacertfile.c_str());
EXPECT_CALL(manager, restartService("nslcd.service")).Times(1);
EXPECT_CALL(manager, restartService("nscd.service")).Times(1);
- manager.createConfig("ldap://9.194.251.136/", "cn=Users,dc=com",
- "cn=Users,dc=corp", "MyLdap12",
- ldap_base::Create::SearchScope::sub,
- ldap_base::Create::Type::ActiveDirectory);
-
+ manager.createConfig(
+ "ldap://9.194.251.136/", "cn=Users,dc=com", "cn=Users,dc=corp",
+ "MyLdap12", ldap_base::Create::SearchScope::sub,
+ ldap_base::Create::Type::ActiveDirectory, "uid", "gid");
+ manager.getConfigPtr()->enabled(true);
EXPECT_TRUE(fs::exists(configFilePath));
EXPECT_EQ(manager.getConfigPtr()->lDAPServerURI(), "ldap://9.194.251.136/");
EXPECT_EQ(manager.getConfigPtr()->lDAPBindDN(), "cn=Users,dc=com");
@@ -106,6 +106,8 @@ TEST_F(TestLDAPConfig, testCreate)
ldap_base::Config::SearchScope::sub);
EXPECT_EQ(manager.getConfigPtr()->lDAPType(),
ldap_base::Config::Type::ActiveDirectory);
+ EXPECT_EQ(manager.getConfigPtr()->userNameAttribute(), "uid");
+ EXPECT_EQ(manager.getConfigPtr()->groupNameAttribute(), "gid");
}
TEST_F(TestLDAPConfig, testRestores)
@@ -120,12 +122,13 @@ TEST_F(TestLDAPConfig, testRestores)
EXPECT_FALSE(fs::exists(configFilePath));
MockConfigMgr* managerPtr = new MockConfigMgr(
bus, LDAP_CONFIG_ROOT, configFilePath.c_str(), tlsCacertfile.c_str());
- EXPECT_CALL(*managerPtr, restartService("nslcd.service")).Times(2);
+ EXPECT_CALL(*managerPtr, restartService("nslcd.service")).Times(1);
EXPECT_CALL(*managerPtr, restartService("nscd.service")).Times(2);
- managerPtr->createConfig("ldap://9.194.251.138/", "cn=Users,dc=com",
- "cn=Users,dc=corp", "MyLdap12",
- ldap_base::Create::SearchScope::sub,
- ldap_base::Create::Type::ActiveDirectory);
+ managerPtr->createConfig(
+ "ldap://9.194.251.138/", "cn=Users,dc=com", "cn=Users,dc=corp",
+ "MyLdap12", ldap_base::Create::SearchScope::sub,
+ ldap_base::Create::Type::ActiveDirectory, "uid", "gid");
+ managerPtr->getConfigPtr()->enabled(true);
EXPECT_TRUE(fs::exists(configFilePath));
// Delete LDAP configuration
managerPtr->deleteObject();
@@ -141,6 +144,8 @@ TEST_F(TestLDAPConfig, testRestores)
ldap_base::Config::SearchScope::sub);
EXPECT_EQ(managerPtr->getConfigPtr()->lDAPType(),
ldap_base::Config::Type::ActiveDirectory);
+ EXPECT_EQ(managerPtr->getConfigPtr()->userNameAttribute(), "uid");
+ EXPECT_EQ(managerPtr->getConfigPtr()->groupNameAttribute(), "gid");
delete managerPtr;
}
@@ -156,13 +161,14 @@ TEST_F(TestLDAPConfig, testLDAPServerURI)
EXPECT_FALSE(fs::exists(configFilePath));
MockConfigMgr* managerPtr = new MockConfigMgr(
bus, LDAP_CONFIG_ROOT, configFilePath.c_str(), tlsCacertfile.c_str());
- EXPECT_CALL(*managerPtr, restartService("nslcd.service")).Times(3);
+ EXPECT_CALL(*managerPtr, restartService("nslcd.service")).Times(2);
EXPECT_CALL(*managerPtr, restartService("nscd.service")).Times(2);
- managerPtr->createConfig("ldap://9.194.251.138/", "cn=Users,dc=com",
- "cn=Users,dc=corp", "MyLdap12",
- ldap_base::Create::SearchScope::sub,
- ldap_base::Create::Type::ActiveDirectory);
+ managerPtr->createConfig(
+ "ldap://9.194.251.138/", "cn=Users,dc=com", "cn=Users,dc=corp",
+ "MyLdap12", ldap_base::Create::SearchScope::sub,
+ ldap_base::Create::Type::ActiveDirectory, "attr1", "attr2");
+ managerPtr->getConfigPtr()->enabled(true);
// Change LDAP Server URI
managerPtr->getConfigPtr()->lDAPServerURI("ldap://9.194.251.139/");
EXPECT_EQ(managerPtr->getConfigPtr()->lDAPServerURI(),
@@ -195,13 +201,14 @@ TEST_F(TestLDAPConfig, testLDAPBindDN)
EXPECT_FALSE(fs::exists(configFilePath));
MockConfigMgr* managerPtr = new MockConfigMgr(
bus, LDAP_CONFIG_ROOT, configFilePath.c_str(), tlsCacertfile.c_str());
- EXPECT_CALL(*managerPtr, restartService("nslcd.service")).Times(3);
+ EXPECT_CALL(*managerPtr, restartService("nslcd.service")).Times(2);
EXPECT_CALL(*managerPtr, restartService("nscd.service")).Times(2);
- managerPtr->createConfig("ldap://9.194.251.138/", "cn=Users,dc=com",
- "cn=Users,dc=corp", "MyLdap12",
- ldap_base::Create::SearchScope::sub,
- ldap_base::Create::Type::ActiveDirectory);
+ managerPtr->createConfig(
+ "ldap://9.194.251.138/", "cn=Users,dc=com", "cn=Users,dc=corp",
+ "MyLdap12", ldap_base::Create::SearchScope::sub,
+ ldap_base::Create::Type::ActiveDirectory, "attr1", "attr2");
+ managerPtr->getConfigPtr()->enabled(true);
// Change LDAP BindDN
managerPtr->getConfigPtr()->lDAPBindDN(
"cn=Administrator,cn=Users,dc=corp,dc=ibm,dc=com");
@@ -242,12 +249,13 @@ TEST_F(TestLDAPConfig, testLDAPBaseDN)
EXPECT_FALSE(fs::exists(configFilePath));
MockConfigMgr* managerPtr = new MockConfigMgr(
bus, LDAP_CONFIG_ROOT, configFilePath.c_str(), tlsCacertfile.c_str());
- EXPECT_CALL(*managerPtr, restartService("nslcd.service")).Times(3);
+ EXPECT_CALL(*managerPtr, restartService("nslcd.service")).Times(2);
EXPECT_CALL(*managerPtr, restartService("nscd.service")).Times(2);
- managerPtr->createConfig("ldap://9.194.251.138/", "cn=Users,dc=com",
- "cn=Users,dc=corp", "MyLdap12",
- ldap_base::Create::SearchScope::sub,
- ldap_base::Create::Type::ActiveDirectory);
+ managerPtr->createConfig(
+ "ldap://9.194.251.138/", "cn=Users,dc=com", "cn=Users,dc=corp",
+ "MyLdap12", ldap_base::Create::SearchScope::sub,
+ ldap_base::Create::Type::ActiveDirectory, "attr1", "attr2");
+ managerPtr->getConfigPtr()->enabled(true);
// Change LDAP BaseDN
managerPtr->getConfigPtr()->lDAPBaseDN(
"cn=Administrator,cn=Users,dc=corp,dc=ibm,dc=com");
@@ -288,12 +296,13 @@ TEST_F(TestLDAPConfig, testSearchScope)
EXPECT_FALSE(fs::exists(configFilePath));
MockConfigMgr* managerPtr = new MockConfigMgr(
bus, LDAP_CONFIG_ROOT, configFilePath.c_str(), tlsCacertfile.c_str());
- EXPECT_CALL(*managerPtr, restartService("nslcd.service")).Times(3);
+ EXPECT_CALL(*managerPtr, restartService("nslcd.service")).Times(2);
EXPECT_CALL(*managerPtr, restartService("nscd.service")).Times(2);
- managerPtr->createConfig("ldap://9.194.251.138/", "cn=Users,dc=com",
- "cn=Users,dc=corp", "MyLdap12",
- ldap_base::Create::SearchScope::sub,
- ldap_base::Create::Type::ActiveDirectory);
+ managerPtr->createConfig(
+ "ldap://9.194.251.138/", "cn=Users,dc=com", "cn=Users,dc=corp",
+ "MyLdap12", ldap_base::Create::SearchScope::sub,
+ ldap_base::Create::Type::ActiveDirectory, "attr1", "attr2");
+ managerPtr->getConfigPtr()->enabled(true);
// Change LDAP SearchScope
managerPtr->getConfigPtr()->lDAPSearchScope(
ldap_base::Config::SearchScope::one);
@@ -321,12 +330,13 @@ TEST_F(TestLDAPConfig, testLDAPType)
EXPECT_FALSE(fs::exists(configFilePath));
MockConfigMgr* managerPtr = new MockConfigMgr(
bus, LDAP_CONFIG_ROOT, configFilePath.c_str(), tlsCacertfile.c_str());
- EXPECT_CALL(*managerPtr, restartService("nslcd.service")).Times(3);
+ EXPECT_CALL(*managerPtr, restartService("nslcd.service")).Times(2);
EXPECT_CALL(*managerPtr, restartService("nscd.service")).Times(2);
- managerPtr->createConfig("ldap://9.194.251.138/", "cn=Users,dc=com",
- "cn=Users,dc=corp", "MyLdap12",
- ldap_base::Create::SearchScope::sub,
- ldap_base::Create::Type::ActiveDirectory);
+ managerPtr->createConfig(
+ "ldap://9.194.251.138/", "cn=Users,dc=com", "cn=Users,dc=corp",
+ "MyLdap12", ldap_base::Create::SearchScope::sub,
+ ldap_base::Create::Type::ActiveDirectory, "attr1", "attr2");
+ managerPtr->getConfigPtr()->enabled(true);
// Change LDAP type
managerPtr->getConfigPtr()->lDAPType(ldap_base::Config::Type::OpenLdap);
EXPECT_EQ(managerPtr->getConfigPtr()->lDAPType(),
diff --git a/user_mgr.cpp b/user_mgr.cpp
index 1cbd43a..47edf7d 100644
--- a/user_mgr.cpp
+++ b/user_mgr.cpp
@@ -64,6 +64,18 @@ static constexpr const char *unlockTimeout = "unlock_time";
static constexpr const char *pamPasswdConfigFile = "/etc/pam.d/common-password";
static constexpr const char *pamAuthConfigFile = "/etc/pam.d/common-auth";
+// Object Manager related
+static constexpr const char *ldapMgrObjBasePath =
+ "/xyz/openbmc_project/user/ldap";
+
+// Object Mapper related
+static constexpr const char *objMapperService =
+ "xyz.openbmc_project.ObjectMapper";
+static constexpr const char *objMapperPath =
+ "/xyz/openbmc_project/object_mapper";
+static constexpr const char *objMapperInterface =
+ "xyz.openbmc_project.ObjectMapper";
+
using namespace phosphor::logging;
using InsufficientPermission =
sdbusplus::xyz::openbmc_project::Common::Error::InsufficientPermission;
@@ -77,7 +89,6 @@ using UserNameDoesNotExist =
sdbusplus::xyz::openbmc_project::User::Common::Error::UserNameDoesNotExist;
using UserNameGroupFail =
sdbusplus::xyz::openbmc_project::User::Common::Error::UserNameGroupFail;
-
using NoResource =
sdbusplus::xyz::openbmc_project::User::Common::Error::NoResource;
@@ -815,6 +826,194 @@ std::vector<std::string> UserMgr::getUsersInGroup(const std::string &groupName)
return usersInGroup;
}
+DbusUserObj UserMgr::getPrivilegeMapperObject(void)
+{
+ DbusUserObj objects;
+ try
+ {
+ std::string basePath = "/xyz/openbmc_project/user/ldap";
+ std::string interface = "xyz.openbmc_project.User.PrivilegeMapper";
+
+ auto ldapMgmtService =
+ getServiceName(std::move(basePath), std::move(interface));
+
+ auto method = bus.new_method_call(
+ ldapMgmtService.c_str(), ldapMgrObjBasePath,
+ "org.freedesktop.DBus.ObjectManager", "GetManagedObjects");
+
+ auto reply = bus.call(method);
+ reply.read(objects);
+ }
+ catch (const InternalFailure &e)
+ {
+ log<level::ERR>("Unable to get the User Service",
+ entry("WHAT=%s", e.what()));
+ throw;
+ }
+ catch (const sdbusplus::exception::SdBusError &e)
+ {
+ log<level::ERR>(
+ "Failed to excute method", entry("METHOD=%s", "GetManagedObjects"),
+ entry("PATH=%s", ldapMgrObjBasePath), entry("WHAT=%s", e.what()));
+ throw;
+ }
+ return objects;
+}
+
+std::string UserMgr::getLdapGroupName(const std::string &userName)
+{
+ struct passwd pwd
+ {
+ };
+ struct passwd *pwdPtr = nullptr;
+ auto buflen = sysconf(_SC_GETPW_R_SIZE_MAX);
+ if (buflen < -1)
+ {
+ // Use a default size if there is no hard limit suggested by sysconf()
+ buflen = 1024;
+ }
+ std::vector<char> buffer(buflen);
+ gid_t gid = 0;
+
+ auto status =
+ getpwnam_r(userName.c_str(), &pwd, buffer.data(), buflen, &pwdPtr);
+ // On success, getpwnam_r() returns zero, and set *pwdPtr to pwd.
+ // If no matching password record was found, these functions return 0
+ // and store NULL in *pwdPtr
+ if (!status && (&pwd == pwdPtr))
+ {
+ gid = pwd.pw_gid;
+ }
+ else
+ {
+ log<level::ERR>("User does not exist",
+ entry("USER_NAME=%s", userName.c_str()));
+ elog<UserNameDoesNotExist>();
+ }
+
+ struct group *groups = nullptr;
+ std::string ldapGroupName;
+
+ while ((groups = getgrent()) != NULL)
+ {
+ if (groups->gr_gid == gid)
+ {
+ ldapGroupName = groups->gr_name;
+ break;
+ }
+ }
+ // Call endgrent() to close the group database.
+ endgrent();
+
+ return ldapGroupName;
+}
+
+std::string UserMgr::getServiceName(std::string &&path, std::string &&intf)
+{
+ auto mapperCall = bus.new_method_call(objMapperService, objMapperPath,
+ objMapperInterface, "GetObject");
+
+ mapperCall.append(std::move(path));
+ mapperCall.append(std::vector<std::string>({std::move(intf)}));
+
+ auto mapperResponseMsg = bus.call(mapperCall);
+
+ if (mapperResponseMsg.is_method_error())
+ {
+ log<level::ERR>("Error in mapper call");
+ elog<InternalFailure>();
+ }
+
+ std::map<std::string, std::vector<std::string>> mapperResponse;
+ mapperResponseMsg.read(mapperResponse);
+
+ if (mapperResponse.begin() == mapperResponse.end())
+ {
+ log<level::ERR>("Invalid response from mapper");
+ elog<InternalFailure>();
+ }
+
+ return mapperResponse.begin()->first;
+}
+
+UserInfoMap UserMgr::getUserInfo(std::string userName)
+{
+ UserInfoMap userInfo;
+ // Check whether the given user is local user or not.
+ if (isUserExist(userName) == true)
+ {
+ const auto &user = usersList[userName];
+ userInfo.emplace("UserPrivilege", user.get()->userPrivilege());
+ userInfo.emplace("UserGroups", user.get()->userGroups());
+ userInfo.emplace("UserEnabled", user.get()->userEnabled());
+ userInfo.emplace("UserLockedForFailedAttempt",
+ user.get()->userLockedForFailedAttempt());
+ userInfo.emplace("RemoteUser", false);
+ }
+ else
+ {
+ std::string ldapGroupName = getLdapGroupName(userName);
+ if (ldapGroupName.empty())
+ {
+ log<level::ERR>("Unable to get group name",
+ entry("USER_NAME=%s", userName.c_str()));
+ elog<InternalFailure>();
+ }
+
+ DbusUserObj objects = getPrivilegeMapperObject();
+
+ std::string privilege;
+ std::string groupName;
+
+ try
+ {
+ for (const auto &objpath : objects)
+ {
+ auto iter = objpath.second.find(
+ "xyz.openbmc_project.User.PrivilegeMapperEntry");
+ if (iter == objpath.second.end())
+ {
+ log<level::ERR>(
+ "Error in finding privilege mapper entry interface");
+ elog<InternalFailure>();
+ }
+ for (const auto &property : iter->second)
+ {
+ auto value =
+ sdbusplus::message::variant_ns::get<std::string>(
+ property.second);
+ if (property.first == "GroupName")
+ {
+ groupName = value;
+ }
+ else if (property.first == "Privilege")
+ {
+ privilege = value;
+ }
+ if (groupName == ldapGroupName)
+ {
+ userInfo["UserPrivilege"] = privilege;
+ }
+ }
+ }
+ auto priv = std::get<std::string>(userInfo["UserPrivilege"]);
+ if (priv.empty())
+ {
+ log<level::ERR>("LDAP group privilege mapping does not exist");
+ }
+ }
+ catch (const std::bad_variant_access &e)
+ {
+ log<level::ERR>("Error while accessing variant",
+ entry("WHAT=%s", e.what()));
+ elog<InternalFailure>();
+ }
+ userInfo.emplace("RemoteUser", true);
+ }
+
+ return userInfo;
+}
+
void UserMgr::initUserObjects(void)
{
// All user management lock has to be based on /etc/shadow
diff --git a/user_mgr.hpp b/user_mgr.hpp
index c1673f1..c78174d 100644
--- a/user_mgr.hpp
+++ b/user_mgr.hpp
@@ -19,6 +19,7 @@
#include <xyz/openbmc_project/User/Manager/server.hpp>
#include <xyz/openbmc_project/User/AccountPolicy/server.hpp>
#include <unordered_map>
+#include <variant>
#include "users.hpp"
namespace phosphor
@@ -32,6 +33,27 @@ using UserSSHLists =
using AccountPolicyIface =
sdbusplus::xyz::openbmc_project::User::server::AccountPolicy;
+using Privilege = std::string;
+using GroupList = std::vector<std::string>;
+using UserEnabled = bool;
+using PropertyName = std::string;
+
+using UserInfo = std::variant<Privilege, GroupList, UserEnabled>;
+using UserInfoMap = std::map<PropertyName, UserInfo>;
+
+using DbusUserObjPath = sdbusplus::message::object_path;
+
+using DbusUserPropVariant = sdbusplus::message::variant<Privilege>;
+
+using DbusUserObjProperties =
+ std::vector<std::pair<PropertyName, DbusUserPropVariant>>;
+
+using Interface = std::string;
+
+using DbusUserObjValue = std::map<Interface, DbusUserObjProperties>;
+
+using DbusUserObj = std::map<DbusUserObjPath, DbusUserObjValue>;
+
/** @class UserMgr
* @brief Responsible for managing user accounts over the D-Bus interface.
*/
@@ -141,6 +163,17 @@ class UserMgr : public UserMgrIface, AccountPolicyIface
bool userLockedForFailedAttempt(const std::string &userName,
const bool &value);
+ /** @brief returns user info
+ * Checks if user is local user, then returns map of properties of user.
+ * like user privilege, list of user groups, user enabled state and user
+ * locked state. If its not local user, then it checks if its a ldap user,
+ * then it gets the privilege mapping of the LDAP group.
+ *
+ * @param[in] - user name
+ * @return - map of user properties
+ **/
+ UserInfoMap getUserInfo(std::string userName) override;
+
private:
/** @brief sdbusplus handler */
sdbusplus::bus::bus &bus;
@@ -275,6 +308,30 @@ class UserMgr : public UserMgrIface, AccountPolicyIface
int setPamModuleArgValue(const std::string &moduleName,
const std::string &argName,
const std::string &argValue);
+
+ /** @brief get service name
+ * method to get dbus service name
+ *
+ * @param[in] path - object path
+ * @param[in] intf - interface
+ * @return - service name
+ */
+ std::string getServiceName(std::string &&path, std::string &&intf);
+
+ /** @brief get LDAP group name
+ * method to get LDAP group name for the given LDAP user
+ *
+ * @param[in] - userName
+ * @return - group name
+ */
+ std::string getLdapGroupName(const std::string &userName);
+
+ /** @brief get privilege mapper object
+ * method to get dbus privilege mapper object
+ *
+ * @return - map of user object
+ */
+ DbusUserObj getPrivilegeMapperObject(void);
};
} // namespace user
OpenPOWER on IntegriCloud