diff options
author | Ratan Gupta <ratagupt@linux.vnet.ibm.com> | 2019-02-11 04:41:52 -0600 |
---|---|---|
committer | Ratan Gupta <ratagupt@linux.vnet.ibm.com> | 2019-03-11 12:00:02 +0530 |
commit | aeaf9413a965d225d11ee1cd2c8ee9aa1f8dc862 (patch) | |
tree | e6abaeaad9709a40b725aafa227306b87645630d /user_mgr.cpp | |
parent | a929752bef26e02ccd103a5669a402ba2b5d5eec (diff) | |
download | phosphor-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>
Diffstat (limited to 'user_mgr.cpp')
-rw-r--r-- | user_mgr.cpp | 201 |
1 files changed, 200 insertions, 1 deletions
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 |