blob: ec205e4c0a3de664bdf943d4f0615cf1f3f61fed [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 Zhouda401fe2022-10-25 00:07:18 +000044inline constexpr size_t maxSystemGroupNameLength = 32;
45inline constexpr size_t maxSystemGroupCount = 64;
Nan Zhou49c81362022-10-25 00:07:08 +000046
Richard Marian Thomaiyar9f630d92018-05-24 10:49:10 +053047using UserMgrIface = sdbusplus::xyz::openbmc_project::User::server::Manager;
48using UserSSHLists =
49 std::pair<std::vector<std::string>, std::vector<std::string>>;
Richard Marian Thomaiyar9164fd92018-06-13 16:51:00 +053050using AccountPolicyIface =
51 sdbusplus::xyz::openbmc_project::User::server::AccountPolicy;
52
Patrick Williamsb3ef4e12022-07-22 19:26:55 -050053using Ifaces = sdbusplus::server::object_t<UserMgrIface, AccountPolicyIface>;
Ratan Gupta1af12232018-11-03 00:35:38 +053054
Ratan Guptaaeaf9412019-02-11 04:41:52 -060055using Privilege = std::string;
56using GroupList = std::vector<std::string>;
57using UserEnabled = bool;
58using PropertyName = std::string;
Ravi Teja5fe724a2019-05-07 05:14:42 -050059using ServiceEnabled = bool;
Ratan Guptaaeaf9412019-02-11 04:41:52 -060060
61using UserInfo = std::variant<Privilege, GroupList, UserEnabled>;
62using UserInfoMap = std::map<PropertyName, UserInfo>;
63
64using DbusUserObjPath = sdbusplus::message::object_path;
65
Patrick Williamsfdf09372020-05-13 18:01:45 -050066using DbusUserPropVariant = std::variant<Privilege, ServiceEnabled>;
Ratan Guptaaeaf9412019-02-11 04:41:52 -060067
Alexander Filippov75626582022-02-09 18:42:37 +030068using DbusUserObjProperties = std::map<PropertyName, DbusUserPropVariant>;
Ratan Guptaaeaf9412019-02-11 04:41:52 -060069
70using Interface = std::string;
71
72using DbusUserObjValue = std::map<Interface, DbusUserObjProperties>;
73
74using DbusUserObj = std::map<DbusUserObjPath, DbusUserObjValue>;
75
Nan Zhoue47c09d2022-10-25 00:06:41 +000076std::string getCSVFromVector(std::span<const std::string> vec);
77
Nan Zhou332fb9d2022-10-25 00:07:03 +000078bool removeStringFromCSV(std::string& csvStr, const std::string& delStr);
79
Nan Zhou8a11d992022-10-25 00:07:06 +000080template <typename... ArgTypes>
Nan Zhou49c81362022-10-25 00:07:08 +000081std::vector<std::string> executeCmd(const char* path, ArgTypes&&... tArgs)
82{
83 std::vector<std::string> stdOutput;
84 boost::process::ipstream stdOutStream;
85 boost::process::child execProg(path, const_cast<char*>(tArgs)...,
86 boost::process::std_out > stdOutStream);
87 std::string stdOutLine;
88
89 while (stdOutStream && std::getline(stdOutStream, stdOutLine) &&
90 !stdOutLine.empty())
91 {
92 stdOutput.emplace_back(stdOutLine);
93 }
94
95 execProg.wait();
96
97 int retCode = execProg.exit_code();
98 if (retCode)
99 {
100 phosphor::logging::log<phosphor::logging::level::ERR>(
101 "Command execution failed",
102 phosphor::logging::entry("PATH=%s", path),
103 phosphor::logging::entry("RETURN_CODE=%d", retCode));
104 phosphor::logging::elog<
105 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure>();
106 }
107
108 return stdOutput;
109}
Nan Zhou8a11d992022-10-25 00:07:06 +0000110
Richard Marian Thomaiyar9f630d92018-05-24 10:49:10 +0530111/** @class UserMgr
112 * @brief Responsible for managing user accounts over the D-Bus interface.
113 */
Ratan Gupta1af12232018-11-03 00:35:38 +0530114class UserMgr : public Ifaces
Richard Marian Thomaiyar9f630d92018-05-24 10:49:10 +0530115{
116 public:
117 UserMgr() = delete;
118 ~UserMgr() = default;
Patrick Williams9638afb2021-02-22 17:16:24 -0600119 UserMgr(const UserMgr&) = delete;
120 UserMgr& operator=(const UserMgr&) = delete;
121 UserMgr(UserMgr&&) = delete;
122 UserMgr& operator=(UserMgr&&) = delete;
Richard Marian Thomaiyar9f630d92018-05-24 10:49:10 +0530123
124 /** @brief Constructs UserMgr object.
125 *
126 * @param[in] bus - sdbusplus handler
127 * @param[in] path - D-Bus path
128 */
Patrick Williamsb3ef4e12022-07-22 19:26:55 -0500129 UserMgr(sdbusplus::bus_t& bus, const char* path);
Richard Marian Thomaiyar9f630d92018-05-24 10:49:10 +0530130
131 /** @brief create user method.
132 * This method creates a new user as requested
133 *
134 * @param[in] userName - Name of the user which has to be created
135 * @param[in] groupNames - Group names list, to which user has to be added.
136 * @param[in] priv - Privilege of the user.
137 * @param[in] enabled - State of the user enabled / disabled.
138 */
139 void createUser(std::string userName, std::vector<std::string> groupNames,
140 std::string priv, bool enabled) override;
141
142 /** @brief rename user method.
143 * This method renames the user as requested
144 *
145 * @param[in] userName - current name of the user
146 * @param[in] newUserName - new user name to which it has to be renamed.
147 */
148 void renameUser(std::string userName, std::string newUserName) override;
149
150 /** @brief delete user method.
151 * This method deletes the user as requested
152 *
153 * @param[in] userName - Name of the user which has to be deleted
154 */
155 void deleteUser(std::string userName);
156
157 /** @brief Update user groups & privilege.
158 * This method updates user groups & privilege
159 *
160 * @param[in] userName - user name, for which update is requested
161 * @param[in] groupName - Group to be updated..
162 * @param[in] priv - Privilege to be updated.
163 */
Patrick Williams9638afb2021-02-22 17:16:24 -0600164 void updateGroupsAndPriv(const std::string& userName,
Nan Zhoufef63032022-10-25 00:07:12 +0000165 std::vector<std::string> groups,
Patrick Williams9638afb2021-02-22 17:16:24 -0600166 const std::string& priv);
Richard Marian Thomaiyar9f630d92018-05-24 10:49:10 +0530167
168 /** @brief Update user enabled state.
169 * This method enables / disables user
170 *
171 * @param[in] userName - user name, for which update is requested
172 * @param[in] enabled - enable / disable the user
173 */
Patrick Williams9638afb2021-02-22 17:16:24 -0600174 void userEnable(const std::string& userName, bool enabled);
Richard Marian Thomaiyar9f630d92018-05-24 10:49:10 +0530175
Richard Marian Thomaiyar9164fd92018-06-13 16:51:00 +0530176 /** @brief update minimum password length requirement
177 *
178 * @param[in] val - minimum password length
179 * @return - minimum password length
180 */
181 uint8_t minPasswordLength(uint8_t val) override;
182
183 /** @brief update old password history count
184 *
185 * @param[in] val - number of times old passwords has to be avoided
186 * @return - number of times old password has to be avoided
187 */
188 uint8_t rememberOldPasswordTimes(uint8_t val) override;
189
190 /** @brief update maximum number of failed login attempt before locked
191 * out.
192 *
193 * @param[in] val - number of allowed attempt
194 * @return - number of allowed attempt
195 */
196 uint16_t maxLoginAttemptBeforeLockout(uint16_t val) override;
197
198 /** @brief update timeout to unlock the account
199 *
200 * @param[in] val - value in seconds
201 * @return - value in seconds
202 */
203 uint32_t accountUnlockTimeout(uint32_t val) override;
204
Richard Marian Thomaiyarc7045192018-06-13 16:51:00 +0530205 /** @brief lists user locked state for failed attempt
206 *
207 * @param[in] - user name
208 * @return - true / false indicating user locked / un-locked
209 **/
Patrick Williams9638afb2021-02-22 17:16:24 -0600210 virtual bool userLockedForFailedAttempt(const std::string& userName);
Richard Marian Thomaiyarc7045192018-06-13 16:51:00 +0530211
212 /** @brief lists user locked state for failed attempt
213 *
214 * @param[in]: user name
215 * @param[in]: value - false -unlock user account, true - no action taken
216 **/
Patrick Williams9638afb2021-02-22 17:16:24 -0600217 bool userLockedForFailedAttempt(const std::string& userName,
218 const bool& value);
Richard Marian Thomaiyarc7045192018-06-13 16:51:00 +0530219
Joseph Reynolds3ab6cc22020-03-03 14:09:03 -0600220 /** @brief shows if the user's password is expired
221 *
222 * @param[in]: user name
223 * @return - true / false indicating user password expired
224 **/
Patrick Williams9638afb2021-02-22 17:16:24 -0600225 virtual bool userPasswordExpired(const std::string& userName);
Joseph Reynolds3ab6cc22020-03-03 14:09:03 -0600226
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600227 /** @brief returns user info
228 * Checks if user is local user, then returns map of properties of user.
229 * like user privilege, list of user groups, user enabled state and user
230 * locked state. If its not local user, then it checks if its a ldap user,
231 * then it gets the privilege mapping of the LDAP group.
232 *
233 * @param[in] - user name
234 * @return - map of user properties
235 **/
236 UserInfoMap getUserInfo(std::string userName) override;
237
Nan Zhou49c81362022-10-25 00:07:08 +0000238 /** @brief get IPMI user count
239 * method to get IPMI user count
240 *
241 * @return - returns user count
242 */
243 virtual size_t getIpmiUsersCount(void);
244
Nan Zhouda401fe2022-10-25 00:07:18 +0000245 void createGroup(std::string groupName) override;
246
247 void deleteGroup(std::string groupName) override;
248
249 static std::vector<std::string> readAllGroupsOnSystem();
250
Nan Zhoue48085d2022-10-25 00:07:04 +0000251 protected:
252 /** @brief get pam argument value
253 * method to get argument value from pam configuration
254 *
255 * @param[in] moduleName - name of the module from where arg has to be read
256 * @param[in] argName - argument name
257 * @param[out] argValue - argument value
258 *
259 * @return 0 - success state of the function
260 */
261 int getPamModuleArgValue(const std::string& moduleName,
262 const std::string& argName, std::string& argValue);
263
264 /** @brief set pam argument value
265 * method to set argument value in pam configuration
266 *
267 * @param[in] moduleName - name of the module in which argument value has
268 * to be set
269 * @param[in] argName - argument name
270 * @param[out] argValue - argument value
271 *
272 * @return 0 - success state of the function
273 */
274 int setPamModuleArgValue(const std::string& moduleName,
275 const std::string& argName,
276 const std::string& argValue);
277
Nan Zhou8a11d992022-10-25 00:07:06 +0000278 /** @brief check for user presence
279 * method to check for user existence
280 *
281 * @param[in] userName - name of the user
282 * @return -true if user exists and false if not.
283 */
284 bool isUserExist(const std::string& userName);
285
Nan Zhou49c81362022-10-25 00:07:08 +0000286 size_t getNonIpmiUsersCount();
287
Nan Zhou8a11d992022-10-25 00:07:06 +0000288 /** @brief check user exists
289 * method to check whether user exist, and throw if not.
290 *
291 * @param[in] userName - name of the user
292 */
293 void throwForUserDoesNotExist(const std::string& userName);
294
295 /** @brief check user does not exist
296 * method to check whether does not exist, and throw if exists.
297 *
298 * @param[in] userName - name of the user
299 */
300 void throwForUserExists(const std::string& userName);
301
Nan Zhou40e44972022-10-25 00:07:07 +0000302 /** @brief check user name constraints
303 * method to check user name constraints and throw if failed.
304 *
305 * @param[in] userName - name of the user
306 * @param[in] groupNames - user groups
307 */
308 void
309 throwForUserNameConstraints(const std::string& userName,
310 const std::vector<std::string>& groupNames);
311
Nan Zhou49c81362022-10-25 00:07:08 +0000312 /** @brief check group user count
313 * method to check max group user count, and throw if limit reached
314 *
315 * @param[in] groupNames - group name
316 */
317 void throwForMaxGrpUserCount(const std::vector<std::string>& groupNames);
318
319 virtual void executeUserAdd(const char* userName, const char* groups,
320 bool sshRequested, bool enabled);
321
322 virtual void executeUserDelete(const char* userName);
323
Nan Zhouf25443e2022-10-25 00:07:11 +0000324 virtual void executeUserRename(const char* userName,
325 const char* newUserName);
326
Nan Zhoufef63032022-10-25 00:07:12 +0000327 virtual void executeUserModify(const char* userName, const char* newGroups,
328 bool sshRequested);
329
Nan Zhou6b6f2d82022-10-25 00:07:17 +0000330 virtual void executeUserModifyUserEnable(const char* userName,
331 bool enabled);
332
Nan Zhouda401fe2022-10-25 00:07:18 +0000333 virtual void executeGroupCreation(const char* groupName);
Nan Zhou86040c22022-11-17 02:08:24 +0000334
Nan Zhouda401fe2022-10-25 00:07:18 +0000335 virtual void executeGroupDeletion(const char* groupName);
Nan Zhou86040c22022-11-17 02:08:24 +0000336
Nan Zhoua2953032022-11-11 21:50:32 +0000337 virtual std::vector<std::string> getFailedAttempt(const char* userName);
338
Nan Zhou589aeb42022-10-25 00:07:09 +0000339 /** @brief check for valid privielge
340 * method to check valid privilege, and throw if invalid
341 *
342 * @param[in] priv - privilege of the user
343 */
344 void throwForInvalidPrivilege(const std::string& priv);
345
Nan Zhouecf88762022-10-25 00:07:10 +0000346 /** @brief check for valid groups
347 * method to check valid groups, and throw if invalid
348 *
349 * @param[in] groupNames - user groups
350 */
351 void throwForInvalidGroups(const std::vector<std::string>& groupName);
352
Nan Zhou4bc69812022-10-25 00:07:13 +0000353 void initializeAccountPolicy();
354
Nan Zhouda401fe2022-10-25 00:07:18 +0000355 /** @brief checks if the group creation meets all constraints
356 * @param groupName - group to check
357 */
358 void checkCreateGroupConstraints(const std::string& groupName);
359
360 /** @brief checks if the group deletion meets all constraints
361 * @param groupName - group to check
362 */
363 void checkDeleteGroupConstraints(const std::string& groupName);
364
365 /** @brief checks if the group name is legal and whether it's allowed to
366 * change. The daemon doesn't allow arbitrary group to be created
367 * @param groupName - group to check
368 */
369 void checkAndThrowForDisallowedGroupCreation(const std::string& groupName);
370
Richard Marian Thomaiyar9f630d92018-05-24 10:49:10 +0530371 private:
372 /** @brief sdbusplus handler */
Patrick Williamsb3ef4e12022-07-22 19:26:55 -0500373 sdbusplus::bus_t& bus;
Richard Marian Thomaiyar9f630d92018-05-24 10:49:10 +0530374
375 /** @brief object path */
376 const std::string path;
377
378 /** @brief privilege manager container */
Nan Zhouda401fe2022-10-25 00:07:18 +0000379 const std::vector<std::string> privMgr = {"priv-admin", "priv-operator",
380 "priv-user"};
Richard Marian Thomaiyar9f630d92018-05-24 10:49:10 +0530381
382 /** @brief groups manager container */
Nan Zhouda401fe2022-10-25 00:07:18 +0000383 std::vector<std::string> groupsMgr;
Richard Marian Thomaiyar9f630d92018-05-24 10:49:10 +0530384
385 /** @brief map container to hold users object */
386 using UserName = std::string;
387 std::unordered_map<UserName, std::unique_ptr<phosphor::user::Users>>
388 usersList;
389
390 /** @brief get users in group
391 * method to get group user list
392 *
393 * @param[in] groupName - group name
394 *
395 * @return userList - list of users in the group.
396 */
Patrick Williams9638afb2021-02-22 17:16:24 -0600397 std::vector<std::string> getUsersInGroup(const std::string& groupName);
Richard Marian Thomaiyar9f630d92018-05-24 10:49:10 +0530398
399 /** @brief get user & SSH users list
400 * method to get the users and ssh users list.
401 *
402 *@return - vector of User & SSH user lists
403 */
404 UserSSHLists getUserAndSshGrpList(void);
405
Richard Marian Thomaiyar9f630d92018-05-24 10:49:10 +0530406 /** @brief get user enabled state
407 * method to get user enabled state.
408 *
409 * @param[in] userName - name of the user
410 * @return - user enabled status (true/false)
411 */
Patrick Williams9638afb2021-02-22 17:16:24 -0600412 bool isUserEnabled(const std::string& userName);
Richard Marian Thomaiyar9f630d92018-05-24 10:49:10 +0530413
414 /** @brief initialize the user manager objects
415 * method to initialize the user manager objects accordingly
416 *
417 */
418 void initUserObjects(void);
419
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600420 /** @brief get service name
421 * method to get dbus service name
422 *
423 * @param[in] path - object path
424 * @param[in] intf - interface
425 * @return - service name
426 */
Patrick Williams9638afb2021-02-22 17:16:24 -0600427 std::string getServiceName(std::string&& path, std::string&& intf);
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600428
Alexander Filippov75626582022-02-09 18:42:37 +0300429 /** @brief get primary group ID of specified user
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600430 *
Alexander Filippov75626582022-02-09 18:42:37 +0300431 * @param[in] - userName
432 * @return - primary group ID
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600433 */
Alexander Filippov75626582022-02-09 18:42:37 +0300434 virtual gid_t getPrimaryGroup(const std::string& userName) const;
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600435
Alexander Filippov75626582022-02-09 18:42:37 +0300436 /** @brief check whether if the user is a member of the group
437 *
438 * @param[in] - userName
439 * @param[in] - ID of the user's primary group
440 * @param[in] - groupName
441 * @return - true if the user is a member of the group
442 */
443 virtual bool isGroupMember(const std::string& userName, gid_t primaryGid,
444 const std::string& groupName) const;
445
446 protected:
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600447 /** @brief get privilege mapper object
448 * method to get dbus privilege mapper object
449 *
450 * @return - map of user object
451 */
raviteja-b8cc44052019-02-27 23:29:36 -0600452 virtual DbusUserObj getPrivilegeMapperObject(void);
453
454 friend class TestUserMgr;
Nan Zhoue48085d2022-10-25 00:07:04 +0000455
456 std::string pamPasswdConfigFile;
457 std::string pamAuthConfigFile;
Richard Marian Thomaiyar9f630d92018-05-24 10:49:10 +0530458};
459
460} // namespace user
461} // namespace phosphor