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