xref: /openbmc/phosphor-user-manager/user_mgr.hpp (revision 86040c2256c191d31ad0264e8a6f4b96d0d7ef9d)
1 /*
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
17 #include "users.hpp"
18 
19 #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>
24 #include <sdbusplus/bus.hpp>
25 #include <sdbusplus/server/object.hpp>
26 #include <xyz/openbmc_project/Common/error.hpp>
27 #include <xyz/openbmc_project/User/AccountPolicy/server.hpp>
28 #include <xyz/openbmc_project/User/Manager/server.hpp>
29 
30 #include <span>
31 #include <string>
32 #include <unordered_map>
33 #include <variant>
34 #include <vector>
35 
36 namespace phosphor
37 {
38 namespace user
39 {
40 
41 inline constexpr size_t ipmiMaxUsers = 15;
42 inline constexpr size_t maxSystemUsers = 30;
43 inline constexpr uint8_t minPasswdLength = 8;
44 
45 using UserMgrIface = sdbusplus::xyz::openbmc_project::User::server::Manager;
46 using UserSSHLists =
47     std::pair<std::vector<std::string>, std::vector<std::string>>;
48 using AccountPolicyIface =
49     sdbusplus::xyz::openbmc_project::User::server::AccountPolicy;
50 
51 using Ifaces = sdbusplus::server::object_t<UserMgrIface, AccountPolicyIface>;
52 
53 using Privilege = std::string;
54 using GroupList = std::vector<std::string>;
55 using UserEnabled = bool;
56 using PropertyName = std::string;
57 using ServiceEnabled = bool;
58 
59 using UserInfo = std::variant<Privilege, GroupList, UserEnabled>;
60 using UserInfoMap = std::map<PropertyName, UserInfo>;
61 
62 using DbusUserObjPath = sdbusplus::message::object_path;
63 
64 using DbusUserPropVariant = std::variant<Privilege, ServiceEnabled>;
65 
66 using DbusUserObjProperties =
67     std::vector<std::pair<PropertyName, DbusUserPropVariant>>;
68 
69 using Interface = std::string;
70 
71 using DbusUserObjValue = std::map<Interface, DbusUserObjProperties>;
72 
73 using DbusUserObj = std::map<DbusUserObjPath, DbusUserObjValue>;
74 
75 std::string getCSVFromVector(std::span<const std::string> vec);
76 
77 bool removeStringFromCSV(std::string& csvStr, const std::string& delStr);
78 
79 template <typename... ArgTypes>
80 std::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 }
109 
110 /** @class UserMgr
111  *  @brief Responsible for managing user accounts over the D-Bus interface.
112  */
113 class UserMgr : public Ifaces
114 {
115   public:
116     UserMgr() = delete;
117     ~UserMgr() = default;
118     UserMgr(const UserMgr&) = delete;
119     UserMgr& operator=(const UserMgr&) = delete;
120     UserMgr(UserMgr&&) = delete;
121     UserMgr& operator=(UserMgr&&) = delete;
122 
123     /** @brief Constructs UserMgr object.
124      *
125      *  @param[in] bus  - sdbusplus handler
126      *  @param[in] path - D-Bus path
127      */
128     UserMgr(sdbusplus::bus_t& bus, const char* path);
129 
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      */
163     void updateGroupsAndPriv(const std::string& userName,
164                              std::vector<std::string> groups,
165                              const std::string& priv);
166 
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      */
173     void userEnable(const std::string& userName, bool enabled);
174 
175     /** @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 
204     /** @brief lists user locked state for failed attempt
205      *
206      * @param[in] - user name
207      * @return - true / false indicating user locked / un-locked
208      **/
209     virtual bool userLockedForFailedAttempt(const std::string& userName);
210 
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      **/
216     bool userLockedForFailedAttempt(const std::string& userName,
217                                     const bool& value);
218 
219     /** @brief shows if the user's password is expired
220      *
221      * @param[in]: user name
222      * @return - true / false indicating user password expired
223      **/
224     virtual bool userPasswordExpired(const std::string& userName);
225 
226     /** @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 
237     /** @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 
244   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 
271     /** @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 
279     size_t getNonIpmiUsersCount();
280 
281     /** @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 
295     /** @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 
305     /** @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 
317     virtual void executeUserRename(const char* userName,
318                                    const char* newUserName);
319 
320     virtual void executeUserModify(const char* userName, const char* newGroups,
321                                    bool sshRequested);
322 
323     virtual void executeUserModifyUserEnable(const char* userName,
324                                              bool enabled);
325 
326     void createGroup(std::string groupName) override;
327 
328     void deleteGroup(std::string groupName) override;
329 
330     virtual std::vector<std::string> getFailedAttempt(const char* userName);
331 
332     /** @brief check for valid privielge
333      *  method to check valid privilege, and throw if invalid
334      *
335      *  @param[in] priv - privilege of the user
336      */
337     void throwForInvalidPrivilege(const std::string& priv);
338 
339     /** @brief check for valid groups
340      *  method to check valid groups, and throw if invalid
341      *
342      *  @param[in] groupNames - user groups
343      */
344     void throwForInvalidGroups(const std::vector<std::string>& groupName);
345 
346     void initializeAccountPolicy();
347 
348   private:
349     /** @brief sdbusplus handler */
350     sdbusplus::bus_t& bus;
351 
352     /** @brief object path */
353     const std::string path;
354 
355     /** @brief privilege manager container */
356     std::vector<std::string> privMgr = {"priv-admin", "priv-operator",
357                                         "priv-user"};
358 
359     /** @brief groups manager container */
360     std::vector<std::string> groupsMgr = {"web", "redfish", "ipmi", "ssh"};
361 
362     /** @brief map container to hold users object */
363     using UserName = std::string;
364     std::unordered_map<UserName, std::unique_ptr<phosphor::user::Users>>
365         usersList;
366 
367     /** @brief get users in group
368      *  method to get group user list
369      *
370      *  @param[in] groupName - group name
371      *
372      *  @return userList  - list of users in the group.
373      */
374     std::vector<std::string> getUsersInGroup(const std::string& groupName);
375 
376     /** @brief get user & SSH users list
377      *  method to get the users and ssh users list.
378      *
379      *@return - vector of User & SSH user lists
380      */
381     UserSSHLists getUserAndSshGrpList(void);
382 
383     /** @brief get user enabled state
384      *  method to get user enabled state.
385      *
386      *  @param[in] userName - name of the user
387      *  @return - user enabled status (true/false)
388      */
389     bool isUserEnabled(const std::string& userName);
390 
391     /** @brief initialize the user manager objects
392      *  method to initialize the user manager objects accordingly
393      *
394      */
395     void initUserObjects(void);
396 
397     /** @brief get service name
398      *  method to get dbus service name
399      *
400      *  @param[in] path - object path
401      *  @param[in] intf - interface
402      *  @return - service name
403      */
404     std::string getServiceName(std::string&& path, std::string&& intf);
405 
406   protected:
407     /** @brief get LDAP group name
408      *  method to get LDAP group name for the given LDAP user
409      *
410      *  @param[in] - userName
411      *  @return - group name
412      */
413     virtual std::string getLdapGroupName(const std::string& userName);
414 
415     /** @brief get privilege mapper object
416      *  method to get dbus privilege mapper object
417      *
418      *  @return - map of user object
419      */
420     virtual DbusUserObj getPrivilegeMapperObject(void);
421 
422     friend class TestUserMgr;
423 
424     std::string pamPasswdConfigFile;
425     std::string pamAuthConfigFile;
426 };
427 
428 } // namespace user
429 } // namespace phosphor
430