diff options
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 |