xref: /openbmc/phosphor-host-ipmid/user_channel/user_mgmt.hpp (revision b0d1396156ae1b96f3364d17dd27d80de69b3971)
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 "user_layer.hpp"
18 
19 #include <boost/interprocess/sync/file_lock.hpp>
20 #include <boost/interprocess/sync/named_recursive_mutex.hpp>
21 #include <ipmid/api.hpp>
22 #include <sdbusplus/bus.hpp>
23 
24 #include <algorithm>
25 #include <cstdint>
26 #include <cstring>
27 #include <ctime>
28 #include <variant>
29 
30 namespace ipmi
31 {
32 
33 static constexpr const char* dBusPropertiesInterface =
34     "org.freedesktop.DBus.Properties";
35 static constexpr const char* getAllPropertiesMethod = "GetAll";
36 static constexpr const char* propertiesChangedSignal = "PropertiesChanged";
37 static constexpr const char* setPropertiesMethod = "Set";
38 
39 // Object Manager related
40 static constexpr const char* dBusObjManager =
41     "org.freedesktop.DBus.ObjectManager";
42 static constexpr const char* getManagedObjectsMethod = "GetManagedObjects";
43 // Object Manager signals
44 static constexpr const char* intfAddedSignal = "InterfacesAdded";
45 static constexpr const char* intfRemovedSignal = "InterfacesRemoved";
46 
47 static constexpr const char* ipmiUserMutex = "ipmi_usr_mutex";
48 static constexpr const char* ipmiMutexCleanupLockFile =
49     "/run/ipmi/ipmi_usr_mutex_cleanup";
50 static constexpr const char* ipmiUserSignalLockFile =
51     "/run/ipmi/ipmi_usr_signal_mutex";
52 static constexpr const char* ipmiUserDataFile = "/var/lib/ipmi/ipmi_user.json";
53 static constexpr const char* ipmiGrpName = "ipmi";
54 static constexpr size_t privNoAccess = 0xF;
55 static constexpr size_t privMask = 0xF;
56 
57 // User manager related
58 static constexpr const char* userMgrService =
59     "xyz.openbmc_project.User.Manager";
60 static constexpr const char* userMgrObjBasePath = "/xyz/openbmc_project/user";
61 static constexpr const char* userObjBasePath = "/xyz/openbmc_project/user";
62 static constexpr const char* userMgrInterface =
63     "xyz.openbmc_project.User.Manager";
64 static constexpr const char* usersInterface =
65     "xyz.openbmc_project.User.Attributes";
66 static constexpr const char* deleteUserInterface =
67     "xyz.openbmc_project.Object.Delete";
68 
69 static constexpr const char* createUserMethod = "CreateUser";
70 static constexpr const char* deleteUserMethod = "Delete";
71 static constexpr const char* renameUserMethod = "RenameUser";
72 // User manager signal memebers
73 static constexpr const char* userRenamedSignal = "UserRenamed";
74 // Mgr interface properties
75 static constexpr const char* allPrivProperty = "AllPrivileges";
76 static constexpr const char* allGrpProperty = "AllGroups";
77 // User interface properties
78 static constexpr const char* userPrivProperty = "UserPrivilege";
79 static constexpr const char* userGrpProperty = "UserGroups";
80 static constexpr const char* userEnabledProperty = "UserEnabled";
81 
82 static std::array<std::string, (PRIVILEGE_OEM + 1)> ipmiPrivIndex = {
83     "priv-reserved", // PRIVILEGE_RESERVED - 0
84     "priv-callback", // PRIVILEGE_CALLBACK - 1
85     "priv-user",     // PRIVILEGE_USER - 2
86     "priv-operator", // PRIVILEGE_OPERATOR - 3
87     "priv-admin",    // PRIVILEGE_ADMIN - 4
88     "priv-custom"    // PRIVILEGE_OEM - 5
89 };
90 
91 // Inline functions for safe username buffer operations
safeUsernameLength(const uint8_t * buf)92 inline size_t safeUsernameLength(const uint8_t* buf)
93 {
94     return strnlen(reinterpret_cast<const char*>(buf), ipmiMaxUserName);
95 }
96 
safeUsernameString(const uint8_t * buf)97 inline std::string safeUsernameString(const uint8_t* buf)
98 {
99     return std::string(reinterpret_cast<const char*>(buf),
100                        safeUsernameLength(buf));
101 }
102 
safeUsernameAssign(std::string & str,const uint8_t * buf)103 inline void safeUsernameAssign(std::string& str, const uint8_t* buf)
104 {
105     size_t len = safeUsernameLength(buf);
106     str.assign(reinterpret_cast<const char*>(buf), len);
107 }
108 
safeUsernameCopyToBuffer(uint8_t * buf,size_t bufSize,const std::string & str)109 inline void safeUsernameCopyToBuffer(uint8_t* buf, size_t bufSize,
110                                      const std::string& str)
111 {
112     std::memset(buf, 0, bufSize);
113     const size_t n = std::min(str.size(), bufSize);
114     std::memcpy(buf, str.data(), n);
115 }
116 
117 using DbusUserPropVariant =
118     std::variant<std::vector<std::string>, std::string, bool>;
119 
120 using DbusUserObjPath = sdbusplus::message::object_path;
121 
122 using DbusUserObjProperties =
123     std::vector<std::pair<std::string, DbusUserPropVariant>>;
124 
125 using DbusUserObjValue = std::map<std::string, DbusUserObjProperties>;
126 
127 /**
128  * @enum User update events.
129  */
130 enum class UserUpdateEvent
131 {
132     reservedEvent,
133     userCreated,
134     userDeleted,
135     userRenamed,
136     userGrpUpdated,
137     userPrivUpdated,
138     userStateUpdated
139 };
140 
141 /** @struct UserPrivAccess
142  *
143  *  Structure for user privilege access (refer spec sec 22.22)
144  */
145 struct UserPrivAccess
146 {
147     uint8_t privilege;
148     bool ipmiEnabled;
149     bool linkAuthEnabled;
150     bool accessCallback;
151 };
152 
153 /** @struct UserInfo
154  *
155  *  Structure for user related information
156  */
157 struct UserInfo
158 {
159     uint8_t userName[ipmiMaxUserName];
160     UserPrivAccess userPrivAccess[ipmiMaxChannels];
161     bool userEnabled;
162     bool userInSystem;
163     bool fixedUserName;
164     PayloadAccess payloadAccess[ipmiMaxChannels];
165 };
166 
167 /** @struct UsersTbl
168  *
169  *  Structure for array of user related information
170  */
171 struct UsersTbl
172 {
173     //+1 to map with UserId directly. UserId 0 is reserved.
174     UserInfo user[ipmiMaxUsers + 1];
175 };
176 
177 /** @brief PAM User Authentication check
178  *
179  *  @param[in] username - username in string
180  *  @param[in] password	- password in string
181  *
182  *  @return status
183  */
184 bool pamUserCheckAuthenticate(std::string_view username,
185                               std::string_view password);
186 
187 class UserAccess;
188 
189 UserAccess& getUserAccessObject();
190 
191 class UserAccess
192 {
193   public:
194     UserAccess(const UserAccess&) = delete;
195     UserAccess& operator=(const UserAccess&) = delete;
196     UserAccess(UserAccess&&) = delete;
197     UserAccess& operator=(UserAccess&&) = delete;
198 
199     ~UserAccess();
200     UserAccess();
201 
202     /** @brief determines valid channel
203      *
204      *  @param[in] chNum - channel number
205      *
206      *  @return true if valid, false otherwise
207      */
208     static bool isValidChannel(const uint8_t chNum);
209 
210     /** @brief determines valid userId
211      *
212      *  @param[in] userId - user id
213      *
214      *  @return true if valid, false otherwise
215      */
216     static bool isValidUserId(const uint8_t userId);
217 
218     /** @brief determines valid user privilege
219      *
220      *  @param[in] priv - Privilege
221      *
222      *  @return true if valid, false otherwise
223      */
224     static bool isValidPrivilege(const uint8_t priv);
225 
226     /** @brief determines sync index to be mapped with common-user-management
227      *
228      *  @return Index which will be used as sync index
229      */
230     static uint8_t getUsrMgmtSyncIndex();
231 
232     /** @brief Converts system privilege to IPMI privilege
233      *
234      *  @param[in] value - Privilege in string
235      *
236      *  @return CommandPrivilege - IPMI privilege type
237      */
238     static CommandPrivilege convertToIPMIPrivilege(const std::string& value);
239 
240     /** @brief Converts IPMI privilege to system privilege
241      *
242      *  @param[in] value - IPMI privilege
243      *
244      *  @return System privilege in string
245      */
246     static std::string convertToSystemPrivilege(const CommandPrivilege& value);
247 
248     /** @brief determines whether user name is valid
249      *
250      *  @param[in] userNameInChar - user name
251      *
252      *  @return true if valid, false otherwise
253      */
254     bool isValidUserName(const std::string& userName);
255 
256     /** @brief determines whether ipmi is in available groups list
257      *
258      * @return true if ipmi group is present, false otherwise
259      */
260     bool isIpmiInAvailableGroupList();
261 
262     /** @brief provides user id of the user
263      *
264      *  @param[in] userName - user name
265      *
266      *  @return user id of the user, else invalid user id (0xFF), if user not
267      * found
268      */
269     uint8_t getUserId(const std::string& userName);
270 
271     /** @brief provides user information
272      *
273      *  @param[in] userId - user id
274      *
275      *  @return UserInfo for the specified user id
276      */
277     UserInfo* getUserInfo(const uint8_t userId);
278 
279     /** @brief sets user information
280      *
281      *  @param[in] userId - user id
282      *  @param[in] userInfo - user information
283      *
284      */
285     void setUserInfo(const uint8_t userId, UserInfo* userInfo);
286 
287     /** @brief provides user name
288      *
289      *  @param[in] userId - user id
290      *  @param[out] userName - user name
291      *
292      *  @return ccSuccess for success, others for failure.
293      */
294     Cc getUserName(const uint8_t userId, std::string& userName);
295 
296     /** @brief to set user name
297      *
298      *  @param[in] userId - user id
299      *  @param[in] userName - user name
300      *
301      *  @return ccSuccess for success, others for failure.
302      */
303     Cc setUserName(const uint8_t userId, const std::string& userName);
304 
305     /** @brief to set user enabled state
306      *
307      *  @param[in] userId - user id
308      *  @param[in] enabledState - enabled state of the user
309      *
310      *  @return ccSuccess for success, others for failure.
311      */
312     Cc setUserEnabledState(const uint8_t userId, const bool& enabledState);
313 
314     /** @brief to set user password
315      *
316      *  @param[in] userId - user id
317      *  @param[in] userPassword  - new password of the user
318      *
319      *  @return ccSuccess for success, others for failure.
320      */
321     Cc setUserPassword(const uint8_t userId, const char* userPassword);
322 
323     /** @brief to set special user password
324      *
325      *  @param[in] userName - user name
326      *  @param[in] userPassword  - new password of the user
327      *
328      *  @return ccSuccess for success, others for failure.
329      */
330     Cc setSpecialUserPassword(const std::string& userName,
331                               const SecureString& userPassword);
332 
333     /** @brief to set user privilege and access details
334      *
335      *  @param[in] userId - user id
336      *  @param[in] chNum - channel number
337      *  @param[in] privAccess - privilege access
338      *  @param[in] otherPrivUpdates - other privilege update flag to update ipmi
339      * enable, link authentication and access callback
340      *
341      *  @return ccSuccess for success, others for failure.
342      */
343     Cc setUserPrivilegeAccess(const uint8_t userId, const uint8_t chNum,
344                               const UserPrivAccess& privAccess,
345                               const bool& otherPrivUpdates);
346 
347     /** @brief to get user payload access details from userInfo entry.
348      *
349      *  @param[in] userInfo    - userInfo entry in usersTbl.
350      *  @param[out] stdPayload - stdPayloadEnables1 in a 2D-array.
351      *  @param[out] oemPayload - oemPayloadEnables1 in a 2D-array.
352      *
353      *  @details Update the given 2D-arrays using the payload access details
354      *  available in the given userInfo entry (from usersTbl).
355      *  This 2D-array will be mapped to a JSON object (which will be written to
356      *  a JSON file subsequently).
357      */
358     void readPayloadAccessFromUserInfo(
359         const UserInfo& userInfo,
360         std::array<std::array<bool, ipmiMaxChannels>, payloadsPerByte>&
361             stdPayload,
362         std::array<std::array<bool, ipmiMaxChannels>, payloadsPerByte>&
363             oemPayload);
364 
365     /** @brief to update user payload access details in userInfo entry.
366      *
367      *  @param[in] stdPayload - stdPayloadEnables1 in a 2D-array.
368      *  @param[in] oemPayload - oemPayloadEnables1 in a 2D-array.
369      *  @param[out] userInfo  - userInfo entry in usersTbl.
370      *
371      *  @details Update user payload access details of a given userInfo
372      *  entry (in usersTbl) with the information provided in given 2D-arrays.
373      *  This 2D-array was created out of a JSON object (which was created by
374      *  parsing a JSON file).
375      */
376     void updatePayloadAccessInUserInfo(
377         const std::array<std::array<bool, ipmiMaxChannels>, payloadsPerByte>&
378             stdPayload,
379         const std::array<std::array<bool, ipmiMaxChannels>, payloadsPerByte>&
380             oemPayload,
381         UserInfo& userInfo);
382 
383     /** @brief to set user payload access details
384      *
385      *  @param[in] chNum - channel number
386      *  @param[in] operation - Enable / Disable
387      *  @param[in] userId - user id
388      *  @param[in] payloadAccess - payload access
389      *
390      *  @return ccSuccess for success, others for failure.
391      */
392     Cc setUserPayloadAccess(const uint8_t chNum, const uint8_t operation,
393                             const uint8_t userId,
394                             const PayloadAccess& payloadAccess);
395 
396     /** @brief reads user management related data from configuration file
397      *
398      */
399     void readUserData();
400 
401     /** @brief writes user management related data to configuration file
402      *
403      */
404     void writeUserData();
405 
406     /** @brief Funtion which checks and reload configuration file data if
407      * needed.
408      *
409      */
410     void checkAndReloadUserData();
411 
412     /** @brief provides user details from D-Bus user property data
413      *
414      *  @param[in] properties - D-Bus user property
415      *  @param[out] usrGrps - user group details
416      *  @param[out] usrPriv - user privilege
417      *  @param[out] usrEnabled - enabled state of the user.
418      *
419      *  @return 0 for success, -errno for failure.
420      */
421     void getUserProperties(const DbusUserObjProperties& properties,
422                            std::vector<std::string>& usrGrps,
423                            std::string& usrPriv, bool& usrEnabled);
424 
425     /** @brief provides user details from D-Bus user object data
426      *
427      *  @param[in] userObjs - D-Bus user object
428      *  @param[out] usrGrps - user group details
429      *  @param[out] usrPriv - user privilege
430      *  @param[out] usrEnabled - enabled state of the user.
431      *
432      *  @return 0 for success, -errno for failure.
433      */
434     int getUserObjProperties(const DbusUserObjValue& userObjs,
435                              std::vector<std::string>& usrGrps,
436                              std::string& usrPriv, bool& usrEnabled);
437 
438     /** @brief function to add user entry information to the configuration
439      *
440      *  @param[in] userName - user name
441      *  @param[in] priv - privilege of the user
442      *  @param[in] enabled - enabled state of the user
443      *
444      *  @return true for success, false for failure
445      */
446     bool addUserEntry(const std::string& userName, const std::string& priv,
447                       const bool& enabled);
448 
449     /** @brief function to delete user entry based on user index
450      *
451      *  @param[in] usrIdx - user index
452      *
453      */
454     void deleteUserIndex(const size_t& usrIdx);
455 
456     /** @brief function to get users table
457      *
458      */
459     UsersTbl* getUsersTblPtr();
460 
461     std::unique_ptr<boost::interprocess::named_recursive_mutex> userMutex{
462         nullptr};
463 
464   private:
465     UsersTbl usersTbl;
466     std::vector<std::string> availablePrivileges;
467     std::vector<std::string> availableGroups;
468     sdbusplus::bus_t bus;
469     std::timespec fileLastUpdatedTime;
470     bool signalHndlrObject = false;
471     boost::interprocess::file_lock sigHndlrLock;
472     boost::interprocess::file_lock mutexCleanupLock;
473 
474     /** @brief function to get user configuration file timestamp
475      *
476      *  @return time stamp or -EIO for failure
477      */
478     std::timespec getUpdatedFileTime();
479 
480     /** @brief function to available system privileges and groups
481      *
482      */
483     void getSystemPrivAndGroups();
484 
485     /** @brief function to init user data from configuration & D-Bus objects
486      * and to register for signals
487      *
488      */
489     void cacheUserDataFile();
490 };
491 
492 } // namespace ipmi
493