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