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 <ipmid/api.h>
20 
21 #include <boost/interprocess/sync/file_lock.hpp>
22 #include <boost/interprocess/sync/named_recursive_mutex.hpp>
23 #include <cstdint>
24 #include <ctime>
25 #include <sdbusplus/bus.hpp>
26 #include <variant>
27 
28 namespace ipmi
29 {
30 
31 using DbusUserPropVariant =
32     std::variant<std::vector<std::string>, std::string, bool>;
33 
34 using DbusUserObjPath = sdbusplus::message::object_path;
35 
36 using DbusUserObjProperties =
37     std::vector<std::pair<std::string, DbusUserPropVariant>>;
38 
39 using DbusUserObjValue = std::map<std::string, DbusUserObjProperties>;
40 
41 /**
42  * @enum User update events.
43  */
44 enum class UserUpdateEvent
45 {
46     reservedEvent,
47     userCreated,
48     userDeleted,
49     userRenamed,
50     userGrpUpdated,
51     userPrivUpdated,
52     userStateUpdated
53 };
54 
55 /** @struct UserPrivAccess
56  *
57  *  Structure for user privilege access (refer spec sec 22.22)
58  */
59 struct UserPrivAccess
60 {
61     uint8_t privilege;
62     bool ipmiEnabled;
63     bool linkAuthEnabled;
64     bool accessCallback;
65 };
66 
67 /** @struct UserInfo
68  *
69  *  Structure for user related information
70  */
71 struct UserInfo
72 {
73     uint8_t userName[ipmiMaxUserName];
74     UserPrivAccess userPrivAccess[ipmiMaxChannels];
75     bool userEnabled;
76     bool userInSystem;
77     bool fixedUserName;
78     PayloadAccess payloadAccess[ipmiMaxChannels];
79 };
80 
81 /** @struct UsersTbl
82  *
83  *  Structure for array of user related information
84  */
85 struct UsersTbl
86 {
87     //+1 to map with UserId directly. UserId 0 is reserved.
88     UserInfo user[ipmiMaxUsers + 1];
89 };
90 
91 /** @brief PAM User Authentication check
92  *
93  *  @param[in] username - username in string
94  *  @param[in] password	- password in string
95  *
96  *  @return status
97  */
98 bool pamUserCheckAuthenticate(std::string_view username,
99                               std::string_view password);
100 
101 class UserAccess;
102 
103 UserAccess& getUserAccessObject();
104 
105 class UserAccess
106 {
107   public:
108     UserAccess(const UserAccess&) = delete;
109     UserAccess& operator=(const UserAccess&) = delete;
110     UserAccess(UserAccess&&) = delete;
111     UserAccess& operator=(UserAccess&&) = delete;
112 
113     ~UserAccess();
114     UserAccess();
115 
116     /** @brief determines valid channel
117      *
118      *  @param[in] chNum - channel number
119      *
120      *  @return true if valid, false otherwise
121      */
122     static bool isValidChannel(const uint8_t chNum);
123 
124     /** @brief determines valid userId
125      *
126      *  @param[in] userId - user id
127      *
128      *  @return true if valid, false otherwise
129      */
130     static bool isValidUserId(const uint8_t userId);
131 
132     /** @brief determines valid user privilege
133      *
134      *  @param[in] priv - Privilege
135      *
136      *  @return true if valid, false otherwise
137      */
138     static bool isValidPrivilege(const uint8_t priv);
139 
140     /** @brief determines sync index to be mapped with common-user-management
141      *
142      *  @return Index which will be used as sync index
143      */
144     static uint8_t getUsrMgmtSyncIndex();
145 
146     /** @brief Converts system privilege to IPMI privilege
147      *
148      *  @param[in] value - Privilege in string
149      *
150      *  @return CommandPrivilege - IPMI privilege type
151      */
152     static CommandPrivilege convertToIPMIPrivilege(const std::string& value);
153 
154     /** @brief Converts IPMI privilege to system privilege
155      *
156      *  @param[in] value - IPMI privilege
157      *
158      *  @return System privilege in string
159      */
160     static std::string convertToSystemPrivilege(const CommandPrivilege& value);
161 
162     /** @brief determines whether user name is valid
163      *
164      *  @param[in] userNameInChar - user name
165      *
166      *  @return true if valid, false otherwise
167      */
168     bool isValidUserName(const char* userNameInChar);
169 
170     /** @brief provides user id of the user
171      *
172      *  @param[in] userName - user name
173      *
174      *  @return user id of the user, else invalid user id (0xFF), if user not
175      * found
176      */
177     uint8_t getUserId(const std::string& userName);
178 
179     /** @brief provides user information
180      *
181      *  @param[in] userId - user id
182      *
183      *  @return UserInfo for the specified user id
184      */
185     UserInfo* getUserInfo(const uint8_t userId);
186 
187     /** @brief sets user information
188      *
189      *  @param[in] userId - user id
190      *  @param[in] userInfo - user information
191      *
192      */
193     void setUserInfo(const uint8_t userId, UserInfo* userInfo);
194 
195     /** @brief provides user name
196      *
197      *  @param[in] userId - user id
198      *  @param[out] userName - user name
199      *
200      *  @return IPMI_CC_OK for success, others for failure.
201      */
202     ipmi_ret_t getUserName(const uint8_t userId, std::string& userName);
203 
204     /** @brief to set user name
205      *
206      *  @param[in] userId - user id
207      *  @param[in] userNameInChar - user name
208      *
209      *  @return IPMI_CC_OK for success, others for failure.
210      */
211     ipmi_ret_t setUserName(const uint8_t userId, const char* userNameInChar);
212 
213     /** @brief to set user enabled state
214      *
215      *  @param[in] userId - user id
216      *  @param[in] enabledState - enabled state of the user
217      *
218      *  @return IPMI_CC_OK for success, others for failure.
219      */
220     ipmi_ret_t setUserEnabledState(const uint8_t userId,
221                                    const bool& enabledState);
222 
223     /** @brief to set user password
224      *
225      *  @param[in] userId - user id
226      *  @param[in] userPassword  - new password of the user
227      *
228      *  @return IPMI_CC_OK for success, others for failure.
229      */
230     ipmi_ret_t setUserPassword(const uint8_t userId, const char* userPassword);
231 
232     /** @brief to set special user password
233      *
234      *  @param[in] userName - user name
235      *  @param[in] userPassword  - new password of the user
236      *
237      *  @return IPMI_CC_OK for success, others for failure.
238      */
239     ipmi_ret_t setSpecialUserPassword(const std::string& userName,
240                                       const std::string& userPassword);
241 
242     /** @brief to set user privilege and access details
243      *
244      *  @param[in] userId - user id
245      *  @param[in] chNum - channel number
246      *  @param[in] privAccess - privilege access
247      *  @param[in] otherPrivUpdates - other privilege update flag to update ipmi
248      * enable, link authentication and access callback
249      *
250      *  @return IPMI_CC_OK for success, others for failure.
251      */
252     ipmi_ret_t setUserPrivilegeAccess(const uint8_t userId, const uint8_t chNum,
253                                       const UserPrivAccess& privAccess,
254                                       const bool& otherPrivUpdates);
255 
256     /** @brief to get user payload access details from userInfo entry.
257      *
258      *  @param[in] userInfo    - userInfo entry in usersTbl.
259      *  @param[out] stdPayload - stdPayloadEnables1 in a 2D-array.
260      *  @param[out] oemPayload - oemPayloadEnables1 in a 2D-array.
261      *
262      *  @details Update the given 2D-arrays using the payload access details
263      *  available in the given userInfo entry (from usersTbl).
264      *  This 2D-array will be mapped to a JSON object (which will be written to
265      *  a JSON file subsequently).
266      */
267     void readPayloadAccessFromUserInfo(
268         const UserInfo& userInfo,
269         std::array<std::array<bool, ipmiMaxChannels>, payloadsPerByte>&
270             stdPayload,
271         std::array<std::array<bool, ipmiMaxChannels>, payloadsPerByte>&
272             oemPayload);
273 
274     /** @brief to update user payload access details in userInfo entry.
275      *
276      *  @param[in] stdPayload - stdPayloadEnables1 in a 2D-array.
277      *  @param[in] oemPayload - oemPayloadEnables1 in a 2D-array.
278      *  @param[out] userInfo  - userInfo entry in usersTbl.
279      *
280      *  @details Update user payload access details of a given userInfo
281      *  entry (in usersTbl) with the information provided in given 2D-arrays.
282      *  This 2D-array was created out of a JSON object (which was created by
283      *  parsing a JSON file).
284      */
285     void updatePayloadAccessInUserInfo(
286         const std::array<std::array<bool, ipmiMaxChannels>, payloadsPerByte>&
287             stdPayload,
288         const std::array<std::array<bool, ipmiMaxChannels>, payloadsPerByte>&
289             oemPayload,
290         UserInfo& userInfo);
291 
292     /** @brief to set user payload access details
293      *
294      *  @param[in] chNum - channel number
295      *  @param[in] operation - Enable / Disable
296      *  @param[in] userId - user id
297      *  @param[in] payloadAccess - payload access
298      *
299      *  @return IPMI_CC_OK for success, others for failure.
300      */
301     ipmi_ret_t setUserPayloadAccess(const uint8_t chNum,
302                                     const uint8_t operation,
303                                     const uint8_t userId,
304                                     const PayloadAccess& payloadAccess);
305 
306     /** @brief reads user management related data from configuration file
307      *
308      */
309     void readUserData();
310 
311     /** @brief writes user management related data to configuration file
312      *
313      */
314     void writeUserData();
315 
316     /** @brief Funtion which checks and reload configuration file data if
317      * needed.
318      *
319      */
320     void checkAndReloadUserData();
321 
322     /** @brief provides user details from D-Bus user property data
323      *
324      *  @param[in] properties - D-Bus user property
325      *  @param[out] usrGrps - user group details
326      *  @param[out] usrPriv - user privilege
327      *  @param[out] usrEnabled - enabled state of the user.
328      *
329      *  @return 0 for success, -errno for failure.
330      */
331     void getUserProperties(const DbusUserObjProperties& properties,
332                            std::vector<std::string>& usrGrps,
333                            std::string& usrPriv, bool& usrEnabled);
334 
335     /** @brief provides user details from D-Bus user object data
336      *
337      *  @param[in] userObjs - D-Bus user object
338      *  @param[out] usrGrps - user group details
339      *  @param[out] usrPriv - user privilege
340      *  @param[out] usrEnabled - enabled state of the user.
341      *
342      *  @return 0 for success, -errno for failure.
343      */
344     int getUserObjProperties(const DbusUserObjValue& userObjs,
345                              std::vector<std::string>& usrGrps,
346                              std::string& usrPriv, bool& usrEnabled);
347 
348     /** @brief function to add user entry information to the configuration
349      *
350      *  @param[in] userName - user name
351      *  @param[in] priv - privilege of the user
352      *  @param[in] enabled - enabled state of the user
353      *
354      *  @return true for success, false for failure
355      */
356     bool addUserEntry(const std::string& userName, const std::string& priv,
357                       const bool& enabled);
358 
359     /** @brief function to delete user entry based on user index
360      *
361      *  @param[in] usrIdx - user index
362      *
363      */
364     void deleteUserIndex(const size_t& usrIdx);
365 
366     /** @brief function to get users table
367      *
368      */
369     UsersTbl* getUsersTblPtr();
370 
371     std::unique_ptr<boost::interprocess::named_recursive_mutex> userMutex{
372         nullptr};
373 
374   private:
375     UsersTbl usersTbl;
376     std::vector<std::string> availablePrivileges;
377     std::vector<std::string> availableGroups;
378     sdbusplus::bus::bus bus;
379     std::time_t fileLastUpdatedTime;
380     bool signalHndlrObject = false;
381     boost::interprocess::file_lock sigHndlrLock;
382     boost::interprocess::file_lock mutexCleanupLock;
383 
384     /** @brief function to get user configuration file timestamp
385      *
386      *  @return time stamp or -EIO for failure
387      */
388     std::time_t getUpdatedFileTime();
389 
390     /** @brief function to available system privileges and groups
391      *
392      */
393     void getSystemPrivAndGroups();
394 
395     /** @brief function to init user data from configuration & D-Bus objects
396      *
397      */
398     void initUserDataFile();
399 };
400 } // namespace ipmi
401