blob: d7c5e4d8d3c0d7d591834e2ae8391a042487c573 [file] [log] [blame]
Snehalatha Venkatesh61024d72021-04-08 16:24:39 +00001/*.
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +05302// 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
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +053019#include <boost/interprocess/sync/file_lock.hpp>
20#include <boost/interprocess/sync/named_recursive_mutex.hpp>
jayaprakash Mutyala9fc5fa12019-08-29 15:14:06 +000021#include <ipmid/api.hpp>
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +053022#include <sdbusplus/bus.hpp>
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -050023
Orit Kashanyf7616312025-08-24 04:48:41 -070024#include <algorithm>
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -050025#include <cstdint>
Orit Kashanyf7616312025-08-24 04:48:41 -070026#include <cstring>
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -050027#include <ctime>
Vernon Mauery16b86932019-05-01 08:36:11 -070028#include <variant>
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +053029
30namespace ipmi
31{
32
Thu Nguyenb0d13962025-08-01 22:00:52 +000033static constexpr const char* dBusPropertiesInterface =
34 "org.freedesktop.DBus.Properties";
35static constexpr const char* getAllPropertiesMethod = "GetAll";
36static constexpr const char* propertiesChangedSignal = "PropertiesChanged";
37static constexpr const char* setPropertiesMethod = "Set";
38
39// Object Manager related
40static constexpr const char* dBusObjManager =
41 "org.freedesktop.DBus.ObjectManager";
42static constexpr const char* getManagedObjectsMethod = "GetManagedObjects";
43// Object Manager signals
44static constexpr const char* intfAddedSignal = "InterfacesAdded";
45static constexpr const char* intfRemovedSignal = "InterfacesRemoved";
46
47static constexpr const char* ipmiUserMutex = "ipmi_usr_mutex";
48static constexpr const char* ipmiMutexCleanupLockFile =
49 "/run/ipmi/ipmi_usr_mutex_cleanup";
50static constexpr const char* ipmiUserSignalLockFile =
51 "/run/ipmi/ipmi_usr_signal_mutex";
52static constexpr const char* ipmiUserDataFile = "/var/lib/ipmi/ipmi_user.json";
53static constexpr const char* ipmiGrpName = "ipmi";
54static constexpr size_t privNoAccess = 0xF;
55static constexpr size_t privMask = 0xF;
56
57// User manager related
58static constexpr const char* userMgrService =
59 "xyz.openbmc_project.User.Manager";
60static constexpr const char* userMgrObjBasePath = "/xyz/openbmc_project/user";
61static constexpr const char* userObjBasePath = "/xyz/openbmc_project/user";
62static constexpr const char* userMgrInterface =
63 "xyz.openbmc_project.User.Manager";
64static constexpr const char* usersInterface =
65 "xyz.openbmc_project.User.Attributes";
66static constexpr const char* deleteUserInterface =
67 "xyz.openbmc_project.Object.Delete";
68
69static constexpr const char* createUserMethod = "CreateUser";
70static constexpr const char* deleteUserMethod = "Delete";
71static constexpr const char* renameUserMethod = "RenameUser";
72// User manager signal memebers
73static constexpr const char* userRenamedSignal = "UserRenamed";
74// Mgr interface properties
75static constexpr const char* allPrivProperty = "AllPrivileges";
76static constexpr const char* allGrpProperty = "AllGroups";
77// User interface properties
78static constexpr const char* userPrivProperty = "UserPrivilege";
79static constexpr const char* userGrpProperty = "UserGroups";
80static constexpr const char* userEnabledProperty = "UserEnabled";
81
82static 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
Orit Kashanyf7616312025-08-24 04:48:41 -070091// Inline functions for safe username buffer operations
92inline size_t safeUsernameLength(const uint8_t* buf)
93{
94 return strnlen(reinterpret_cast<const char*>(buf), ipmiMaxUserName);
95}
96
97inline std::string safeUsernameString(const uint8_t* buf)
98{
99 return std::string(reinterpret_cast<const char*>(buf),
100 safeUsernameLength(buf));
101}
102
103inline 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
109inline 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
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530117using DbusUserPropVariant =
Vernon Mauery16b86932019-05-01 08:36:11 -0700118 std::variant<std::vector<std::string>, std::string, bool>;
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530119
120using DbusUserObjPath = sdbusplus::message::object_path;
121
122using DbusUserObjProperties =
123 std::vector<std::pair<std::string, DbusUserPropVariant>>;
124
125using DbusUserObjValue = std::map<std::string, DbusUserObjProperties>;
126
Richard Marian Thomaiyar6e1ba9e2018-11-29 06:29:21 +0530127/**
128 * @enum User update events.
129 */
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530130enum class UserUpdateEvent
131{
132 reservedEvent,
133 userCreated,
134 userDeleted,
135 userRenamed,
136 userGrpUpdated,
137 userPrivUpdated,
138 userStateUpdated
139};
140
Richard Marian Thomaiyar6e1ba9e2018-11-29 06:29:21 +0530141/** @struct UserPrivAccess
142 *
143 * Structure for user privilege access (refer spec sec 22.22)
144 */
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530145struct UserPrivAccess
146{
147 uint8_t privilege;
148 bool ipmiEnabled;
149 bool linkAuthEnabled;
150 bool accessCallback;
151};
152
Richard Marian Thomaiyar6e1ba9e2018-11-29 06:29:21 +0530153/** @struct UserInfo
154 *
155 * Structure for user related information
156 */
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530157struct UserInfo
158{
159 uint8_t userName[ipmiMaxUserName];
160 UserPrivAccess userPrivAccess[ipmiMaxChannels];
161 bool userEnabled;
162 bool userInSystem;
163 bool fixedUserName;
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000164 PayloadAccess payloadAccess[ipmiMaxChannels];
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530165};
166
Richard Marian Thomaiyar6e1ba9e2018-11-29 06:29:21 +0530167/** @struct UsersTbl
168 *
169 * Structure for array of user related information
170 */
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530171struct UsersTbl
172{
173 //+1 to map with UserId directly. UserId 0 is reserved.
174 UserInfo user[ipmiMaxUsers + 1];
175};
176
Ayushi Smriti02650d52019-05-15 11:59:09 +0000177/** @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 */
184bool pamUserCheckAuthenticate(std::string_view username,
185 std::string_view password);
186
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530187class UserAccess;
188
189UserAccess& getUserAccessObject();
190
191class 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 */
Richard Marian Thomaiyara45cb342018-12-03 15:08:59 +0530208 static bool isValidChannel(const uint8_t chNum);
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530209
210 /** @brief determines valid userId
211 *
212 * @param[in] userId - user id
213 *
214 * @return true if valid, false otherwise
215 */
Richard Marian Thomaiyara45cb342018-12-03 15:08:59 +0530216 static bool isValidUserId(const uint8_t userId);
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530217
218 /** @brief determines valid user privilege
219 *
220 * @param[in] priv - Privilege
221 *
222 * @return true if valid, false otherwise
223 */
Richard Marian Thomaiyara45cb342018-12-03 15:08:59 +0530224 static bool isValidPrivilege(const uint8_t priv);
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530225
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 */
jayaprakash Mutyala76363302020-02-14 23:50:38 +0000254 bool isValidUserName(const std::string& userName);
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530255
Richard Marian Thomaiyar489a4ed2020-01-17 11:48:40 +0530256 /** @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
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530262 /** @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 */
Richard Marian Thomaiyara45cb342018-12-03 15:08:59 +0530277 UserInfo* getUserInfo(const uint8_t userId);
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530278
279 /** @brief sets user information
280 *
281 * @param[in] userId - user id
282 * @param[in] userInfo - user information
283 *
284 */
Richard Marian Thomaiyara45cb342018-12-03 15:08:59 +0530285 void setUserInfo(const uint8_t userId, UserInfo* userInfo);
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530286
287 /** @brief provides user name
288 *
289 * @param[in] userId - user id
290 * @param[out] userName - user name
291 *
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000292 * @return ccSuccess for success, others for failure.
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530293 */
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000294 Cc getUserName(const uint8_t userId, std::string& userName);
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530295
296 /** @brief to set user name
297 *
298 * @param[in] userId - user id
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000299 * @param[in] userName - user name
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530300 *
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000301 * @return ccSuccess for success, others for failure.
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530302 */
jayaprakash Mutyala76363302020-02-14 23:50:38 +0000303 Cc setUserName(const uint8_t userId, const std::string& userName);
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530304
Richard Marian Thomaiyar282e79b2018-11-13 19:00:58 +0530305 /** @brief to set user enabled state
306 *
307 * @param[in] userId - user id
308 * @param[in] enabledState - enabled state of the user
309 *
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000310 * @return ccSuccess for success, others for failure.
Richard Marian Thomaiyar282e79b2018-11-13 19:00:58 +0530311 */
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000312 Cc setUserEnabledState(const uint8_t userId, const bool& enabledState);
Richard Marian Thomaiyar282e79b2018-11-13 19:00:58 +0530313
Suryakanth Sekar90b00c72019-01-16 10:37:57 +0530314 /** @brief to set user password
315 *
316 * @param[in] userId - user id
317 * @param[in] userPassword - new password of the user
318 *
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000319 * @return ccSuccess for success, others for failure.
Suryakanth Sekar90b00c72019-01-16 10:37:57 +0530320 */
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000321 Cc setUserPassword(const uint8_t userId, const char* userPassword);
Suryakanth Sekar90b00c72019-01-16 10:37:57 +0530322
Richard Marian Thomaiyar788362c2019-04-14 15:12:47 +0530323 /** @brief to set special user password
324 *
325 * @param[in] userName - user name
326 * @param[in] userPassword - new password of the user
327 *
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000328 * @return ccSuccess for success, others for failure.
Richard Marian Thomaiyar788362c2019-04-14 15:12:47 +0530329 */
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000330 Cc setSpecialUserPassword(const std::string& userName,
Vernon Mauery1e22a0f2021-07-30 13:36:54 -0700331 const SecureString& userPassword);
Richard Marian Thomaiyar788362c2019-04-14 15:12:47 +0530332
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530333 /** @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 *
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000341 * @return ccSuccess for success, others for failure.
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530342 */
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000343 Cc setUserPrivilegeAccess(const uint8_t userId, const uint8_t chNum,
344 const UserPrivAccess& privAccess,
345 const bool& otherPrivUpdates);
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530346
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000347 /** @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 *
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000390 * @return ccSuccess for success, others for failure.
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000391 */
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000392 Cc setUserPayloadAccess(const uint8_t chNum, const uint8_t operation,
393 const uint8_t userId,
394 const PayloadAccess& payloadAccess);
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000395
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530396 /** @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;
Patrick Williams5d82f472022-07-22 19:26:53 -0500468 sdbusplus::bus_t bus;
Jayaprakash Mutyala08d3d062021-10-01 16:01:57 +0000469 std::timespec fileLastUpdatedTime;
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530470 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 */
Jayaprakash Mutyala08d3d062021-10-01 16:01:57 +0000478 std::timespec getUpdatedFileTime();
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530479
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
arun-pmbbe728c2020-01-10 15:18:04 +0530486 * and to register for signals
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530487 *
488 */
arun-pmbbe728c2020-01-10 15:18:04 +0530489 void cacheUserDataFile();
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530490};
Snehalatha Venkatesh61024d72021-04-08 16:24:39 +0000491
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530492} // namespace ipmi