summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRatan Gupta <ratagupt@linux.vnet.ibm.com>2019-02-11 04:41:52 -0600
committerRatan Gupta <ratagupt@linux.vnet.ibm.com>2019-03-11 12:00:02 +0530
commitaeaf9413a965d225d11ee1cd2c8ee9aa1f8dc862 (patch)
treee6abaeaad9709a40b725aafa227306b87645630d
parenta929752bef26e02ccd103a5669a402ba2b5d5eec (diff)
downloadphosphor-user-manager-aeaf9413a965d225d11ee1cd2c8ee9aa1f8dc862.tar.gz
phosphor-user-manager-aeaf9413a965d225d11ee1cd2c8ee9aa1f8dc862.zip
squash the following commits
LDAP: Adding support for extra properties Implement GetUserInfo function in phosphor-user-manager Squashing the commits due to phosphor-dbus-interfaces dependency as the interface gets merged and it requires implementation so it is a deadlock for both the commits. Implement GetUserInfo function in phosphor-user-manager There was need to have api which return privilege for ldap user. it was discussed in this commit https://gerrit.openbmc-project.xyz/#/c/openbmc/phosphor-dbus-interfaces/+/12027/ and decided to have generic api. -Checks if user is local user, then returns map of properties of local 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 get the privilege mapping for the LDAP group and returns. TestedBy: 1) getUserInfo with local user verify user details. 2) getUserInfo with ldap user having privilege mapper entry, verify user details. 3) getUserInfo with no existing user. check for exception UserNameDoesNotExist. Change-Id: I44af41953db60ff96b39498d72839c2ab64bc8bd Signed-off-by: raviteja-b <raviteja28031990@gmail.com> LDAP: Adding support for extra properties This commit also decouple the ldap service(nslcd) start with each property update,Now there is a D-bus property ldap service enabled which controls that whether the LDAP service will be restarted after each property update,so now user have an option to disable the ldap service and do multi- property update and then enable the service again. TestedBy: 1) Create the config with new added properties Verify that it was getting reflected on the D-bus object. 2) After making the change restarted the ldap-conf service Verify that new properties(usernameattr,groupnameattr) are correctly updated. 3) Authenticaton test Verify that LDAP authentication worked fine. 4) Set the enabled property to true Verify that it starts the nslcd service 5) Set the enabled property to false Verify that it stops the nslcd.service 6) Set the enabled property to true and change any other config property Verify that it starts the nslcd.service 7) Set the enabled property to false which stops the nslcd service and change any other config property. Verify that it doesn't start the nslcd service. Change-Id: Ie3ca04a2adbbb1fe113764199348c4f7ac67f648 Signed-off-by: Ratan Gupta <ratagupt@linux.vnet.ibm.com>
-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