blob: e67352770af7bb7e0dd45c430d90fe11d2232f62 [file] [log] [blame]
Richard Marian Thomaiyar9f630d92018-05-24 10:49:10 +05301/*
2// Copyright (c) 2018 Intel Corporation
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8// http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15*/
16#pragma once
Patrick Williams9638afb2021-02-22 17:16:24 -060017#include "users.hpp"
18
Nan Zhou49c81362022-10-25 00:07:08 +000019#include <boost/process/child.hpp>
20#include <boost/process/io.hpp>
21#include <phosphor-logging/elog-errors.hpp>
22#include <phosphor-logging/elog.hpp>
23#include <phosphor-logging/log.hpp>
Richard Marian Thomaiyar9f630d92018-05-24 10:49:10 +053024#include <sdbusplus/bus.hpp>
25#include <sdbusplus/server/object.hpp>
Nan Zhou49c81362022-10-25 00:07:08 +000026#include <xyz/openbmc_project/Common/error.hpp>
Richard Marian Thomaiyar9164fd92018-06-13 16:51:00 +053027#include <xyz/openbmc_project/User/AccountPolicy/server.hpp>
Patrick Williams9638afb2021-02-22 17:16:24 -060028#include <xyz/openbmc_project/User/Manager/server.hpp>
29
Nan Zhoue47c09d2022-10-25 00:06:41 +000030#include <span>
31#include <string>
Richard Marian Thomaiyar9f630d92018-05-24 10:49:10 +053032#include <unordered_map>
Ratan Guptaaeaf9412019-02-11 04:41:52 -060033#include <variant>
Nan Zhoue47c09d2022-10-25 00:06:41 +000034#include <vector>
Richard Marian Thomaiyar9f630d92018-05-24 10:49:10 +053035
36namespace phosphor
37{
38namespace user
39{
40
Nan Zhou49c81362022-10-25 00:07:08 +000041inline constexpr size_t ipmiMaxUsers = 15;
42inline constexpr size_t maxSystemUsers = 30;
Nan Zhou4bc69812022-10-25 00:07:13 +000043inline constexpr uint8_t minPasswdLength = 8;
Nan Zhou49c81362022-10-25 00:07:08 +000044
Richard Marian Thomaiyar9f630d92018-05-24 10:49:10 +053045using UserMgrIface = sdbusplus::xyz::openbmc_project::User::server::Manager;
46using UserSSHLists =
47 std::pair<std::vector<std::string>, std::vector<std::string>>;
Richard Marian Thomaiyar9164fd92018-06-13 16:51:00 +053048using AccountPolicyIface =
49 sdbusplus::xyz::openbmc_project::User::server::AccountPolicy;
50
Patrick Williamsb3ef4e12022-07-22 19:26:55 -050051using Ifaces = sdbusplus::server::object_t<UserMgrIface, AccountPolicyIface>;
Ratan Gupta1af12232018-11-03 00:35:38 +053052
Ratan Guptaaeaf9412019-02-11 04:41:52 -060053using Privilege = std::string;
54using GroupList = std::vector<std::string>;
55using UserEnabled = bool;
56using PropertyName = std::string;
Ravi Teja5fe724a2019-05-07 05:14:42 -050057using ServiceEnabled = bool;
Ratan Guptaaeaf9412019-02-11 04:41:52 -060058
59using UserInfo = std::variant<Privilege, GroupList, UserEnabled>;
60using UserInfoMap = std::map<PropertyName, UserInfo>;
61
62using DbusUserObjPath = sdbusplus::message::object_path;
63
Patrick Williamsfdf09372020-05-13 18:01:45 -050064using DbusUserPropVariant = std::variant<Privilege, ServiceEnabled>;
Ratan Guptaaeaf9412019-02-11 04:41:52 -060065
66using DbusUserObjProperties =
67 std::vector<std::pair<PropertyName, DbusUserPropVariant>>;
68
69using Interface = std::string;
70
71using DbusUserObjValue = std::map<Interface, DbusUserObjProperties>;
72
73using DbusUserObj = std::map<DbusUserObjPath, DbusUserObjValue>;
74
Nan Zhoue47c09d2022-10-25 00:06:41 +000075std::string getCSVFromVector(std::span<const std::string> vec);
76
Nan Zhou332fb9d2022-10-25 00:07:03 +000077bool removeStringFromCSV(std::string& csvStr, const std::string& delStr);
78
Nan Zhou8a11d992022-10-25 00:07:06 +000079template <typename... ArgTypes>
Nan Zhou49c81362022-10-25 00:07:08 +000080std::vector<std::string> executeCmd(const char* path, ArgTypes&&... tArgs)
81{
82 std::vector<std::string> stdOutput;
83 boost::process::ipstream stdOutStream;
84 boost::process::child execProg(path, const_cast<char*>(tArgs)...,
85 boost::process::std_out > stdOutStream);
86 std::string stdOutLine;
87
88 while (stdOutStream && std::getline(stdOutStream, stdOutLine) &&
89 !stdOutLine.empty())
90 {
91 stdOutput.emplace_back(stdOutLine);
92 }
93
94 execProg.wait();
95
96 int retCode = execProg.exit_code();
97 if (retCode)
98 {
99 phosphor::logging::log<phosphor::logging::level::ERR>(
100 "Command execution failed",
101 phosphor::logging::entry("PATH=%s", path),
102 phosphor::logging::entry("RETURN_CODE=%d", retCode));
103 phosphor::logging::elog<
104 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure>();
105 }
106
107 return stdOutput;
108}
Nan Zhou8a11d992022-10-25 00:07:06 +0000109
Richard Marian Thomaiyar9f630d92018-05-24 10:49:10 +0530110/** @class UserMgr
111 * @brief Responsible for managing user accounts over the D-Bus interface.
112 */
Ratan Gupta1af12232018-11-03 00:35:38 +0530113class UserMgr : public Ifaces
Richard Marian Thomaiyar9f630d92018-05-24 10:49:10 +0530114{
115 public:
116 UserMgr() = delete;
117 ~UserMgr() = default;
Patrick Williams9638afb2021-02-22 17:16:24 -0600118 UserMgr(const UserMgr&) = delete;
119 UserMgr& operator=(const UserMgr&) = delete;
120 UserMgr(UserMgr&&) = delete;
121 UserMgr& operator=(UserMgr&&) = delete;
Richard Marian Thomaiyar9f630d92018-05-24 10:49:10 +0530122
123 /** @brief Constructs UserMgr object.
124 *
125 * @param[in] bus - sdbusplus handler
126 * @param[in] path - D-Bus path
127 */
Patrick Williamsb3ef4e12022-07-22 19:26:55 -0500128 UserMgr(sdbusplus::bus_t& bus, const char* path);
Richard Marian Thomaiyar9f630d92018-05-24 10:49:10 +0530129
130 /** @brief create user method.
131 * This method creates a new user as requested
132 *
133 * @param[in] userName - Name of the user which has to be created
134 * @param[in] groupNames - Group names list, to which user has to be added.
135 * @param[in] priv - Privilege of the user.
136 * @param[in] enabled - State of the user enabled / disabled.
137 */
138 void createUser(std::string userName, std::vector<std::string> groupNames,
139 std::string priv, bool enabled) override;
140
141 /** @brief rename user method.
142 * This method renames the user as requested
143 *
144 * @param[in] userName - current name of the user
145 * @param[in] newUserName - new user name to which it has to be renamed.
146 */
147 void renameUser(std::string userName, std::string newUserName) override;
148
149 /** @brief delete user method.
150 * This method deletes the user as requested
151 *
152 * @param[in] userName - Name of the user which has to be deleted
153 */
154 void deleteUser(std::string userName);
155
156 /** @brief Update user groups & privilege.
157 * This method updates user groups & privilege
158 *
159 * @param[in] userName - user name, for which update is requested
160 * @param[in] groupName - Group to be updated..
161 * @param[in] priv - Privilege to be updated.
162 */
Patrick Williams9638afb2021-02-22 17:16:24 -0600163 void updateGroupsAndPriv(const std::string& userName,
Nan Zhoufef63032022-10-25 00:07:12 +0000164 std::vector<std::string> groups,
Patrick Williams9638afb2021-02-22 17:16:24 -0600165 const std::string& priv);
Richard Marian Thomaiyar9f630d92018-05-24 10:49:10 +0530166
167 /** @brief Update user enabled state.
168 * This method enables / disables user
169 *
170 * @param[in] userName - user name, for which update is requested
171 * @param[in] enabled - enable / disable the user
172 */
Patrick Williams9638afb2021-02-22 17:16:24 -0600173 void userEnable(const std::string& userName, bool enabled);
Richard Marian Thomaiyar9f630d92018-05-24 10:49:10 +0530174
Richard Marian Thomaiyar9164fd92018-06-13 16:51:00 +0530175 /** @brief update minimum password length requirement
176 *
177 * @param[in] val - minimum password length
178 * @return - minimum password length
179 */
180 uint8_t minPasswordLength(uint8_t val) override;
181
182 /** @brief update old password history count
183 *
184 * @param[in] val - number of times old passwords has to be avoided
185 * @return - number of times old password has to be avoided
186 */
187 uint8_t rememberOldPasswordTimes(uint8_t val) override;
188
189 /** @brief update maximum number of failed login attempt before locked
190 * out.
191 *
192 * @param[in] val - number of allowed attempt
193 * @return - number of allowed attempt
194 */
195 uint16_t maxLoginAttemptBeforeLockout(uint16_t val) override;
196
197 /** @brief update timeout to unlock the account
198 *
199 * @param[in] val - value in seconds
200 * @return - value in seconds
201 */
202 uint32_t accountUnlockTimeout(uint32_t val) override;
203
Richard Marian Thomaiyarc7045192018-06-13 16:51:00 +0530204 /** @brief lists user locked state for failed attempt
205 *
206 * @param[in] - user name
207 * @return - true / false indicating user locked / un-locked
208 **/
Patrick Williams9638afb2021-02-22 17:16:24 -0600209 virtual bool userLockedForFailedAttempt(const std::string& userName);
Richard Marian Thomaiyarc7045192018-06-13 16:51:00 +0530210
211 /** @brief lists user locked state for failed attempt
212 *
213 * @param[in]: user name
214 * @param[in]: value - false -unlock user account, true - no action taken
215 **/
Patrick Williams9638afb2021-02-22 17:16:24 -0600216 bool userLockedForFailedAttempt(const std::string& userName,
217 const bool& value);
Richard Marian Thomaiyarc7045192018-06-13 16:51:00 +0530218
Joseph Reynolds3ab6cc22020-03-03 14:09:03 -0600219 /** @brief shows if the user's password is expired
220 *
221 * @param[in]: user name
222 * @return - true / false indicating user password expired
223 **/
Patrick Williams9638afb2021-02-22 17:16:24 -0600224 virtual bool userPasswordExpired(const std::string& userName);
Joseph Reynolds3ab6cc22020-03-03 14:09:03 -0600225
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600226 /** @brief returns user info
227 * Checks if user is local user, then returns map of properties of user.
228 * like user privilege, list of user groups, user enabled state and user
229 * locked state. If its not local user, then it checks if its a ldap user,
230 * then it gets the privilege mapping of the LDAP group.
231 *
232 * @param[in] - user name
233 * @return - map of user properties
234 **/
235 UserInfoMap getUserInfo(std::string userName) override;
236
Nan Zhou49c81362022-10-25 00:07:08 +0000237 /** @brief get IPMI user count
238 * method to get IPMI user count
239 *
240 * @return - returns user count
241 */
242 virtual size_t getIpmiUsersCount(void);
243
Nan Zhoue48085d2022-10-25 00:07:04 +0000244 protected:
245 /** @brief get pam argument value
246 * method to get argument value from pam configuration
247 *
248 * @param[in] moduleName - name of the module from where arg has to be read
249 * @param[in] argName - argument name
250 * @param[out] argValue - argument value
251 *
252 * @return 0 - success state of the function
253 */
254 int getPamModuleArgValue(const std::string& moduleName,
255 const std::string& argName, std::string& argValue);
256
257 /** @brief set pam argument value
258 * method to set argument value in pam configuration
259 *
260 * @param[in] moduleName - name of the module in which argument value has
261 * to be set
262 * @param[in] argName - argument name
263 * @param[out] argValue - argument value
264 *
265 * @return 0 - success state of the function
266 */
267 int setPamModuleArgValue(const std::string& moduleName,
268 const std::string& argName,
269 const std::string& argValue);
270
Nan Zhou8a11d992022-10-25 00:07:06 +0000271 /** @brief check for user presence
272 * method to check for user existence
273 *
274 * @param[in] userName - name of the user
275 * @return -true if user exists and false if not.
276 */
277 bool isUserExist(const std::string& userName);
278
Nan Zhou49c81362022-10-25 00:07:08 +0000279 size_t getNonIpmiUsersCount();
280
Nan Zhou8a11d992022-10-25 00:07:06 +0000281 /** @brief check user exists
282 * method to check whether user exist, and throw if not.
283 *
284 * @param[in] userName - name of the user
285 */
286 void throwForUserDoesNotExist(const std::string& userName);
287
288 /** @brief check user does not exist
289 * method to check whether does not exist, and throw if exists.
290 *
291 * @param[in] userName - name of the user
292 */
293 void throwForUserExists(const std::string& userName);
294
Nan Zhou40e44972022-10-25 00:07:07 +0000295 /** @brief check user name constraints
296 * method to check user name constraints and throw if failed.
297 *
298 * @param[in] userName - name of the user
299 * @param[in] groupNames - user groups
300 */
301 void
302 throwForUserNameConstraints(const std::string& userName,
303 const std::vector<std::string>& groupNames);
304
Nan Zhou49c81362022-10-25 00:07:08 +0000305 /** @brief check group user count
306 * method to check max group user count, and throw if limit reached
307 *
308 * @param[in] groupNames - group name
309 */
310 void throwForMaxGrpUserCount(const std::vector<std::string>& groupNames);
311
312 virtual void executeUserAdd(const char* userName, const char* groups,
313 bool sshRequested, bool enabled);
314
315 virtual void executeUserDelete(const char* userName);
316
Nan Zhouf25443e2022-10-25 00:07:11 +0000317 virtual void executeUserRename(const char* userName,
318 const char* newUserName);
319
Nan Zhoufef63032022-10-25 00:07:12 +0000320 virtual void executeUserModify(const char* userName, const char* newGroups,
321 bool sshRequested);
322
Nan Zhou6b6f2d82022-10-25 00:07:17 +0000323 virtual void executeUserModifyUserEnable(const char* userName,
324 bool enabled);
325
Nan Zhoua2953032022-11-11 21:50:32 +0000326 virtual std::vector<std::string> getFailedAttempt(const char* userName);
327
Nan Zhou589aeb42022-10-25 00:07:09 +0000328 /** @brief check for valid privielge
329 * method to check valid privilege, and throw if invalid
330 *
331 * @param[in] priv - privilege of the user
332 */
333 void throwForInvalidPrivilege(const std::string& priv);
334
Nan Zhouecf88762022-10-25 00:07:10 +0000335 /** @brief check for valid groups
336 * method to check valid groups, and throw if invalid
337 *
338 * @param[in] groupNames - user groups
339 */
340 void throwForInvalidGroups(const std::vector<std::string>& groupName);
341
Nan Zhou4bc69812022-10-25 00:07:13 +0000342 void initializeAccountPolicy();
343
Richard Marian Thomaiyar9f630d92018-05-24 10:49:10 +0530344 private:
345 /** @brief sdbusplus handler */
Patrick Williamsb3ef4e12022-07-22 19:26:55 -0500346 sdbusplus::bus_t& bus;
Richard Marian Thomaiyar9f630d92018-05-24 10:49:10 +0530347
348 /** @brief object path */
349 const std::string path;
350
351 /** @brief privilege manager container */
352 std::vector<std::string> privMgr = {"priv-admin", "priv-operator",
Asmitha Karunanithi5c892d12022-03-25 01:32:43 -0500353 "priv-user"};
Richard Marian Thomaiyar9f630d92018-05-24 10:49:10 +0530354
355 /** @brief groups manager container */
356 std::vector<std::string> groupsMgr = {"web", "redfish", "ipmi", "ssh"};
357
358 /** @brief map container to hold users object */
359 using UserName = std::string;
360 std::unordered_map<UserName, std::unique_ptr<phosphor::user::Users>>
361 usersList;
362
363 /** @brief get users in group
364 * method to get group user list
365 *
366 * @param[in] groupName - group name
367 *
368 * @return userList - list of users in the group.
369 */
Patrick Williams9638afb2021-02-22 17:16:24 -0600370 std::vector<std::string> getUsersInGroup(const std::string& groupName);
Richard Marian Thomaiyar9f630d92018-05-24 10:49:10 +0530371
372 /** @brief get user & SSH users list
373 * method to get the users and ssh users list.
374 *
375 *@return - vector of User & SSH user lists
376 */
377 UserSSHLists getUserAndSshGrpList(void);
378
Richard Marian Thomaiyar9f630d92018-05-24 10:49:10 +0530379 /** @brief get user enabled state
380 * method to get user enabled state.
381 *
382 * @param[in] userName - name of the user
383 * @return - user enabled status (true/false)
384 */
Patrick Williams9638afb2021-02-22 17:16:24 -0600385 bool isUserEnabled(const std::string& userName);
Richard Marian Thomaiyar9f630d92018-05-24 10:49:10 +0530386
387 /** @brief initialize the user manager objects
388 * method to initialize the user manager objects accordingly
389 *
390 */
391 void initUserObjects(void);
392
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600393 /** @brief get service name
394 * method to get dbus service name
395 *
396 * @param[in] path - object path
397 * @param[in] intf - interface
398 * @return - service name
399 */
Patrick Williams9638afb2021-02-22 17:16:24 -0600400 std::string getServiceName(std::string&& path, std::string&& intf);
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600401
raviteja-b8cc44052019-02-27 23:29:36 -0600402 protected:
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600403 /** @brief get LDAP group name
404 * method to get LDAP group name for the given LDAP user
405 *
406 * @param[in] - userName
407 * @return - group name
408 */
Patrick Williams9638afb2021-02-22 17:16:24 -0600409 virtual std::string getLdapGroupName(const std::string& userName);
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600410
411 /** @brief get privilege mapper object
412 * method to get dbus privilege mapper object
413 *
414 * @return - map of user object
415 */
raviteja-b8cc44052019-02-27 23:29:36 -0600416 virtual DbusUserObj getPrivilegeMapperObject(void);
417
418 friend class TestUserMgr;
Nan Zhoue48085d2022-10-25 00:07:04 +0000419
420 std::string pamPasswdConfigFile;
421 std::string pamAuthConfigFile;
Richard Marian Thomaiyar9f630d92018-05-24 10:49:10 +0530422};
423
424} // namespace user
425} // namespace phosphor