blob: b057bf0163d571835be30e5f9dd0eaea4a14958a [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;
43
Richard Marian Thomaiyar9f630d92018-05-24 10:49:10 +053044using UserMgrIface = sdbusplus::xyz::openbmc_project::User::server::Manager;
45using UserSSHLists =
46 std::pair<std::vector<std::string>, std::vector<std::string>>;
Richard Marian Thomaiyar9164fd92018-06-13 16:51:00 +053047using AccountPolicyIface =
48 sdbusplus::xyz::openbmc_project::User::server::AccountPolicy;
49
Patrick Williamsb3ef4e12022-07-22 19:26:55 -050050using Ifaces = sdbusplus::server::object_t<UserMgrIface, AccountPolicyIface>;
Ratan Gupta1af12232018-11-03 00:35:38 +053051
Ratan Guptaaeaf9412019-02-11 04:41:52 -060052using Privilege = std::string;
53using GroupList = std::vector<std::string>;
54using UserEnabled = bool;
55using PropertyName = std::string;
Ravi Teja5fe724a2019-05-07 05:14:42 -050056using ServiceEnabled = bool;
Ratan Guptaaeaf9412019-02-11 04:41:52 -060057
58using UserInfo = std::variant<Privilege, GroupList, UserEnabled>;
59using UserInfoMap = std::map<PropertyName, UserInfo>;
60
61using DbusUserObjPath = sdbusplus::message::object_path;
62
Patrick Williamsfdf09372020-05-13 18:01:45 -050063using DbusUserPropVariant = std::variant<Privilege, ServiceEnabled>;
Ratan Guptaaeaf9412019-02-11 04:41:52 -060064
65using DbusUserObjProperties =
66 std::vector<std::pair<PropertyName, DbusUserPropVariant>>;
67
68using Interface = std::string;
69
70using DbusUserObjValue = std::map<Interface, DbusUserObjProperties>;
71
72using DbusUserObj = std::map<DbusUserObjPath, DbusUserObjValue>;
73
Nan Zhoue47c09d2022-10-25 00:06:41 +000074std::string getCSVFromVector(std::span<const std::string> vec);
75
Nan Zhou332fb9d2022-10-25 00:07:03 +000076bool removeStringFromCSV(std::string& csvStr, const std::string& delStr);
77
Nan Zhou8a11d992022-10-25 00:07:06 +000078template <typename... ArgTypes>
Nan Zhou49c81362022-10-25 00:07:08 +000079std::vector<std::string> executeCmd(const char* path, ArgTypes&&... tArgs)
80{
81 std::vector<std::string> stdOutput;
82 boost::process::ipstream stdOutStream;
83 boost::process::child execProg(path, const_cast<char*>(tArgs)...,
84 boost::process::std_out > stdOutStream);
85 std::string stdOutLine;
86
87 while (stdOutStream && std::getline(stdOutStream, stdOutLine) &&
88 !stdOutLine.empty())
89 {
90 stdOutput.emplace_back(stdOutLine);
91 }
92
93 execProg.wait();
94
95 int retCode = execProg.exit_code();
96 if (retCode)
97 {
98 phosphor::logging::log<phosphor::logging::level::ERR>(
99 "Command execution failed",
100 phosphor::logging::entry("PATH=%s", path),
101 phosphor::logging::entry("RETURN_CODE=%d", retCode));
102 phosphor::logging::elog<
103 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure>();
104 }
105
106 return stdOutput;
107}
Nan Zhou8a11d992022-10-25 00:07:06 +0000108
Richard Marian Thomaiyar9f630d92018-05-24 10:49:10 +0530109/** @class UserMgr
110 * @brief Responsible for managing user accounts over the D-Bus interface.
111 */
Ratan Gupta1af12232018-11-03 00:35:38 +0530112class UserMgr : public Ifaces
Richard Marian Thomaiyar9f630d92018-05-24 10:49:10 +0530113{
114 public:
115 UserMgr() = delete;
116 ~UserMgr() = default;
Patrick Williams9638afb2021-02-22 17:16:24 -0600117 UserMgr(const UserMgr&) = delete;
118 UserMgr& operator=(const UserMgr&) = delete;
119 UserMgr(UserMgr&&) = delete;
120 UserMgr& operator=(UserMgr&&) = delete;
Richard Marian Thomaiyar9f630d92018-05-24 10:49:10 +0530121
122 /** @brief Constructs UserMgr object.
123 *
124 * @param[in] bus - sdbusplus handler
125 * @param[in] path - D-Bus path
126 */
Patrick Williamsb3ef4e12022-07-22 19:26:55 -0500127 UserMgr(sdbusplus::bus_t& bus, const char* path);
Richard Marian Thomaiyar9f630d92018-05-24 10:49:10 +0530128
129 /** @brief create user method.
130 * This method creates a new user as requested
131 *
132 * @param[in] userName - Name of the user which has to be created
133 * @param[in] groupNames - Group names list, to which user has to be added.
134 * @param[in] priv - Privilege of the user.
135 * @param[in] enabled - State of the user enabled / disabled.
136 */
137 void createUser(std::string userName, std::vector<std::string> groupNames,
138 std::string priv, bool enabled) override;
139
140 /** @brief rename user method.
141 * This method renames the user as requested
142 *
143 * @param[in] userName - current name of the user
144 * @param[in] newUserName - new user name to which it has to be renamed.
145 */
146 void renameUser(std::string userName, std::string newUserName) override;
147
148 /** @brief delete user method.
149 * This method deletes the user as requested
150 *
151 * @param[in] userName - Name of the user which has to be deleted
152 */
153 void deleteUser(std::string userName);
154
155 /** @brief Update user groups & privilege.
156 * This method updates user groups & privilege
157 *
158 * @param[in] userName - user name, for which update is requested
159 * @param[in] groupName - Group to be updated..
160 * @param[in] priv - Privilege to be updated.
161 */
Patrick Williams9638afb2021-02-22 17:16:24 -0600162 void updateGroupsAndPriv(const std::string& userName,
163 const std::vector<std::string>& groups,
164 const std::string& priv);
Richard Marian Thomaiyar9f630d92018-05-24 10:49:10 +0530165
166 /** @brief Update user enabled state.
167 * This method enables / disables user
168 *
169 * @param[in] userName - user name, for which update is requested
170 * @param[in] enabled - enable / disable the user
171 */
Patrick Williams9638afb2021-02-22 17:16:24 -0600172 void userEnable(const std::string& userName, bool enabled);
Richard Marian Thomaiyar9f630d92018-05-24 10:49:10 +0530173
Richard Marian Thomaiyar9164fd92018-06-13 16:51:00 +0530174 /** @brief update minimum password length requirement
175 *
176 * @param[in] val - minimum password length
177 * @return - minimum password length
178 */
179 uint8_t minPasswordLength(uint8_t val) override;
180
181 /** @brief update old password history count
182 *
183 * @param[in] val - number of times old passwords has to be avoided
184 * @return - number of times old password has to be avoided
185 */
186 uint8_t rememberOldPasswordTimes(uint8_t val) override;
187
188 /** @brief update maximum number of failed login attempt before locked
189 * out.
190 *
191 * @param[in] val - number of allowed attempt
192 * @return - number of allowed attempt
193 */
194 uint16_t maxLoginAttemptBeforeLockout(uint16_t val) override;
195
196 /** @brief update timeout to unlock the account
197 *
198 * @param[in] val - value in seconds
199 * @return - value in seconds
200 */
201 uint32_t accountUnlockTimeout(uint32_t val) override;
202
Richard Marian Thomaiyarc7045192018-06-13 16:51:00 +0530203 /** @brief lists user locked state for failed attempt
204 *
205 * @param[in] - user name
206 * @return - true / false indicating user locked / un-locked
207 **/
Patrick Williams9638afb2021-02-22 17:16:24 -0600208 virtual bool userLockedForFailedAttempt(const std::string& userName);
Richard Marian Thomaiyarc7045192018-06-13 16:51:00 +0530209
210 /** @brief lists user locked state for failed attempt
211 *
212 * @param[in]: user name
213 * @param[in]: value - false -unlock user account, true - no action taken
214 **/
Patrick Williams9638afb2021-02-22 17:16:24 -0600215 bool userLockedForFailedAttempt(const std::string& userName,
216 const bool& value);
Richard Marian Thomaiyarc7045192018-06-13 16:51:00 +0530217
Joseph Reynolds3ab6cc22020-03-03 14:09:03 -0600218 /** @brief shows if the user's password is expired
219 *
220 * @param[in]: user name
221 * @return - true / false indicating user password expired
222 **/
Patrick Williams9638afb2021-02-22 17:16:24 -0600223 virtual bool userPasswordExpired(const std::string& userName);
Joseph Reynolds3ab6cc22020-03-03 14:09:03 -0600224
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600225 /** @brief returns user info
226 * Checks if user is local user, then returns map of properties of user.
227 * like user privilege, list of user groups, user enabled state and user
228 * locked state. If its not local user, then it checks if its a ldap user,
229 * then it gets the privilege mapping of the LDAP group.
230 *
231 * @param[in] - user name
232 * @return - map of user properties
233 **/
234 UserInfoMap getUserInfo(std::string userName) override;
235
Nan Zhou49c81362022-10-25 00:07:08 +0000236 /** @brief get IPMI user count
237 * method to get IPMI user count
238 *
239 * @return - returns user count
240 */
241 virtual size_t getIpmiUsersCount(void);
242
Nan Zhoue48085d2022-10-25 00:07:04 +0000243 protected:
244 /** @brief get pam argument value
245 * method to get argument value from pam configuration
246 *
247 * @param[in] moduleName - name of the module from where arg has to be read
248 * @param[in] argName - argument name
249 * @param[out] argValue - argument value
250 *
251 * @return 0 - success state of the function
252 */
253 int getPamModuleArgValue(const std::string& moduleName,
254 const std::string& argName, std::string& argValue);
255
256 /** @brief set pam argument value
257 * method to set argument value in pam configuration
258 *
259 * @param[in] moduleName - name of the module in which argument value has
260 * to be set
261 * @param[in] argName - argument name
262 * @param[out] argValue - argument value
263 *
264 * @return 0 - success state of the function
265 */
266 int setPamModuleArgValue(const std::string& moduleName,
267 const std::string& argName,
268 const std::string& argValue);
269
Nan Zhou8a11d992022-10-25 00:07:06 +0000270 /** @brief check for user presence
271 * method to check for user existence
272 *
273 * @param[in] userName - name of the user
274 * @return -true if user exists and false if not.
275 */
276 bool isUserExist(const std::string& userName);
277
Nan Zhou49c81362022-10-25 00:07:08 +0000278 size_t getNonIpmiUsersCount();
279
Nan Zhou8a11d992022-10-25 00:07:06 +0000280 /** @brief check user exists
281 * method to check whether user exist, and throw if not.
282 *
283 * @param[in] userName - name of the user
284 */
285 void throwForUserDoesNotExist(const std::string& userName);
286
287 /** @brief check user does not exist
288 * method to check whether does not exist, and throw if exists.
289 *
290 * @param[in] userName - name of the user
291 */
292 void throwForUserExists(const std::string& userName);
293
Nan Zhou40e44972022-10-25 00:07:07 +0000294 /** @brief check user name constraints
295 * method to check user name constraints and throw if failed.
296 *
297 * @param[in] userName - name of the user
298 * @param[in] groupNames - user groups
299 */
300 void
301 throwForUserNameConstraints(const std::string& userName,
302 const std::vector<std::string>& groupNames);
303
Nan Zhou49c81362022-10-25 00:07:08 +0000304 /** @brief check group user count
305 * method to check max group user count, and throw if limit reached
306 *
307 * @param[in] groupNames - group name
308 */
309 void throwForMaxGrpUserCount(const std::vector<std::string>& groupNames);
310
311 virtual void executeUserAdd(const char* userName, const char* groups,
312 bool sshRequested, bool enabled);
313
314 virtual void executeUserDelete(const char* userName);
315
Nan Zhouf25443e2022-10-25 00:07:11 +0000316 virtual void executeUserRename(const char* userName,
317 const char* newUserName);
318
Nan Zhou589aeb42022-10-25 00:07:09 +0000319 /** @brief check for valid privielge
320 * method to check valid privilege, and throw if invalid
321 *
322 * @param[in] priv - privilege of the user
323 */
324 void throwForInvalidPrivilege(const std::string& priv);
325
Nan Zhouecf88762022-10-25 00:07:10 +0000326 /** @brief check for valid groups
327 * method to check valid groups, and throw if invalid
328 *
329 * @param[in] groupNames - user groups
330 */
331 void throwForInvalidGroups(const std::vector<std::string>& groupName);
332
Richard Marian Thomaiyar9f630d92018-05-24 10:49:10 +0530333 private:
334 /** @brief sdbusplus handler */
Patrick Williamsb3ef4e12022-07-22 19:26:55 -0500335 sdbusplus::bus_t& bus;
Richard Marian Thomaiyar9f630d92018-05-24 10:49:10 +0530336
337 /** @brief object path */
338 const std::string path;
339
340 /** @brief privilege manager container */
341 std::vector<std::string> privMgr = {"priv-admin", "priv-operator",
Richard Marian Thomaiyar32be2962019-11-08 17:21:53 +0530342 "priv-user", "priv-noaccess"};
Richard Marian Thomaiyar9f630d92018-05-24 10:49:10 +0530343
344 /** @brief groups manager container */
345 std::vector<std::string> groupsMgr = {"web", "redfish", "ipmi", "ssh"};
346
347 /** @brief map container to hold users object */
348 using UserName = std::string;
349 std::unordered_map<UserName, std::unique_ptr<phosphor::user::Users>>
350 usersList;
351
352 /** @brief get users in group
353 * method to get group user list
354 *
355 * @param[in] groupName - group name
356 *
357 * @return userList - list of users in the group.
358 */
Patrick Williams9638afb2021-02-22 17:16:24 -0600359 std::vector<std::string> getUsersInGroup(const std::string& groupName);
Richard Marian Thomaiyar9f630d92018-05-24 10:49:10 +0530360
361 /** @brief get user & SSH users list
362 * method to get the users and ssh users list.
363 *
364 *@return - vector of User & SSH user lists
365 */
366 UserSSHLists getUserAndSshGrpList(void);
367
Richard Marian Thomaiyar9f630d92018-05-24 10:49:10 +0530368 /** @brief get user enabled state
369 * method to get user enabled state.
370 *
371 * @param[in] userName - name of the user
372 * @return - user enabled status (true/false)
373 */
Patrick Williams9638afb2021-02-22 17:16:24 -0600374 bool isUserEnabled(const std::string& userName);
Richard Marian Thomaiyar9f630d92018-05-24 10:49:10 +0530375
376 /** @brief initialize the user manager objects
377 * method to initialize the user manager objects accordingly
378 *
379 */
380 void initUserObjects(void);
381
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600382 /** @brief get service name
383 * method to get dbus service name
384 *
385 * @param[in] path - object path
386 * @param[in] intf - interface
387 * @return - service name
388 */
Patrick Williams9638afb2021-02-22 17:16:24 -0600389 std::string getServiceName(std::string&& path, std::string&& intf);
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600390
raviteja-b8cc44052019-02-27 23:29:36 -0600391 protected:
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600392 /** @brief get LDAP group name
393 * method to get LDAP group name for the given LDAP user
394 *
395 * @param[in] - userName
396 * @return - group name
397 */
Patrick Williams9638afb2021-02-22 17:16:24 -0600398 virtual std::string getLdapGroupName(const std::string& userName);
Ratan Guptaaeaf9412019-02-11 04:41:52 -0600399
400 /** @brief get privilege mapper object
401 * method to get dbus privilege mapper object
402 *
403 * @return - map of user object
404 */
raviteja-b8cc44052019-02-27 23:29:36 -0600405 virtual DbusUserObj getPrivilegeMapperObject(void);
406
407 friend class TestUserMgr;
Nan Zhoue48085d2022-10-25 00:07:04 +0000408
409 std::string pamPasswdConfigFile;
410 std::string pamAuthConfigFile;
Richard Marian Thomaiyar9f630d92018-05-24 10:49:10 +0530411};
412
413} // namespace user
414} // namespace phosphor