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 };
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 provides user id of the user
170      *
171      *  @param[in] userName - user name
172      *
173      *  @return user id of the user, else invalid user id (0xFF), if user not
174      * found
175      */
176     uint8_t getUserId(const std::string& userName);
177 
178     /** @brief provides user information
179      *
180      *  @param[in] userId - user id
181      *
182      *  @return UserInfo for the specified user id
183      */
184     UserInfo* getUserInfo(const uint8_t userId);
185 
186     /** @brief sets user information
187      *
188      *  @param[in] userId - user id
189      *  @param[in] userInfo - user information
190      *
191      */
192     void setUserInfo(const uint8_t userId, UserInfo* userInfo);
193 
194     /** @brief provides user name
195      *
196      *  @param[in] userId - user id
197      *  @param[out] userName - user name
198      *
199      *  @return IPMI_CC_OK for success, others for failure.
200      */
201     ipmi_ret_t getUserName(const uint8_t userId, std::string& userName);
202 
203     /** @brief to set user name
204      *
205      *  @param[in] userId - user id
206      *  @param[in] userNameInChar - user name
207      *
208      *  @return IPMI_CC_OK for success, others for failure.
209      */
210     ipmi_ret_t setUserName(const uint8_t userId, const char* userNameInChar);
211 
212     /** @brief to set user enabled state
213      *
214      *  @param[in] userId - user id
215      *  @param[in] enabledState - enabled state of the user
216      *
217      *  @return IPMI_CC_OK for success, others for failure.
218      */
219     ipmi_ret_t setUserEnabledState(const uint8_t userId,
220                                    const bool& enabledState);
221 
222     /** @brief to set user password
223      *
224      *  @param[in] userId - user id
225      *  @param[in] userPassword  - new password of the user
226      *
227      *  @return IPMI_CC_OK for success, others for failure.
228      */
229     ipmi_ret_t setUserPassword(const uint8_t userId, const char* userPassword);
230 
231     /** @brief to set special user password
232      *
233      *  @param[in] userName - user name
234      *  @param[in] userPassword  - new password of the user
235      *
236      *  @return IPMI_CC_OK for success, others for failure.
237      */
238     ipmi_ret_t setSpecialUserPassword(const std::string& userName,
239                                       const std::string& userPassword);
240 
241     /** @brief to set user privilege and access details
242      *
243      *  @param[in] userId - user id
244      *  @param[in] chNum - channel number
245      *  @param[in] privAccess - privilege access
246      *  @param[in] otherPrivUpdates - other privilege update flag to update ipmi
247      * enable, link authentication and access callback
248      *
249      *  @return IPMI_CC_OK for success, others for failure.
250      */
251     ipmi_ret_t setUserPrivilegeAccess(const uint8_t userId, const uint8_t chNum,
252                                       const UserPrivAccess& privAccess,
253                                       const bool& otherPrivUpdates);
254 
255     /** @brief reads user management related data from configuration file
256      *
257      */
258     void readUserData();
259 
260     /** @brief writes user management related data to configuration file
261      *
262      */
263     void writeUserData();
264 
265     /** @brief Funtion which checks and reload configuration file data if
266      * needed.
267      *
268      */
269     void checkAndReloadUserData();
270 
271     /** @brief provides user details from D-Bus user property data
272      *
273      *  @param[in] properties - D-Bus user property
274      *  @param[out] usrGrps - user group details
275      *  @param[out] usrPriv - user privilege
276      *  @param[out] usrEnabled - enabled state of the user.
277      *
278      *  @return 0 for success, -errno for failure.
279      */
280     void getUserProperties(const DbusUserObjProperties& properties,
281                            std::vector<std::string>& usrGrps,
282                            std::string& usrPriv, bool& usrEnabled);
283 
284     /** @brief provides user details from D-Bus user object data
285      *
286      *  @param[in] userObjs - D-Bus user object
287      *  @param[out] usrGrps - user group details
288      *  @param[out] usrPriv - user privilege
289      *  @param[out] usrEnabled - enabled state of the user.
290      *
291      *  @return 0 for success, -errno for failure.
292      */
293     int getUserObjProperties(const DbusUserObjValue& userObjs,
294                              std::vector<std::string>& usrGrps,
295                              std::string& usrPriv, bool& usrEnabled);
296 
297     /** @brief function to add user entry information to the configuration
298      *
299      *  @param[in] userName - user name
300      *  @param[in] priv - privilege of the user
301      *  @param[in] enabled - enabled state of the user
302      *
303      *  @return true for success, false for failure
304      */
305     bool addUserEntry(const std::string& userName, const std::string& priv,
306                       const bool& enabled);
307 
308     /** @brief function to delete user entry based on user index
309      *
310      *  @param[in] usrIdx - user index
311      *
312      */
313     void deleteUserIndex(const size_t& usrIdx);
314 
315     /** @brief function to get users table
316      *
317      */
318     UsersTbl* getUsersTblPtr();
319 
320     std::unique_ptr<boost::interprocess::named_recursive_mutex> userMutex{
321         nullptr};
322 
323   private:
324     UsersTbl usersTbl;
325     std::vector<std::string> availablePrivileges;
326     std::vector<std::string> availableGroups;
327     sdbusplus::bus::bus bus;
328     std::time_t fileLastUpdatedTime;
329     bool signalHndlrObject = false;
330     boost::interprocess::file_lock sigHndlrLock;
331     boost::interprocess::file_lock mutexCleanupLock;
332 
333     /** @brief function to get user configuration file timestamp
334      *
335      *  @return time stamp or -EIO for failure
336      */
337     std::time_t getUpdatedFileTime();
338 
339     /** @brief function to available system privileges and groups
340      *
341      */
342     void getSystemPrivAndGroups();
343 
344     /** @brief function to init user data from configuration & D-Bus objects
345      *
346      */
347     void initUserDataFile();
348 };
349 } // namespace ipmi
350