blob: 4a3e24add5ac6e59b7e44e66eb592ffd35386493 [file] [log] [blame]
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +05301/*
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
17#include "usercommands.hpp"
18
19#include "apphandler.hpp"
Richard Marian Thomaiyar06df8762018-12-08 17:38:25 +053020#include "channel_layer.hpp"
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +053021#include "user_layer.hpp"
22
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +053023#include <security/pam_appl.h>
24
Vernon Mauerye08fbff2019-04-03 09:19:34 -070025#include <ipmid/api.hpp>
George Liu82844ef2024-07-17 17:03:56 +080026#include <phosphor-logging/lg2.hpp>
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -050027
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +053028#include <regex>
29
30namespace ipmi
31{
32
Saravanan Palanisamy77381f12019-05-15 22:33:17 +000033static constexpr uint8_t enableOperation = 0x00;
34static constexpr uint8_t disableOperation = 0x01;
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +053035
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +053036/** @brief implements the set user access command
37 * @param ctx - IPMI context pointer (for channel)
38 * @param channel - channel number
39 * @param ipmiEnabled - indicates ipmi messaging state
40 * @param linkAuthEnabled - indicates link authentication state
41 * @param accessCallback - indicates callback state
42 * @param bitsUpdate - indicates update request
43 * @param userId - user id
44 * @param reserved1 - skip 2 bits
45 * @param privilege - user privilege
46 * @param reserved2 - skip 4 bits
47 * @param sessionLimit - optional - unused for now
48 *
49 * @returns ipmi completion code
50 */
Patrick Williams1318a5e2024-08-16 15:19:54 -040051ipmi::RspType<> ipmiSetUserAccess(
52 ipmi::Context::ptr ctx, uint4_t channel, uint1_t ipmiEnabled,
53 uint1_t linkAuthEnabled, uint1_t accessCallback, uint1_t bitsUpdate,
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +053054
Patrick Williams1318a5e2024-08-16 15:19:54 -040055 uint6_t userId, uint2_t reserved1,
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +053056
Patrick Williams1318a5e2024-08-16 15:19:54 -040057 uint4_t privilege, uint4_t reserved2,
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +053058
Patrick Williams1318a5e2024-08-16 15:19:54 -040059 std::optional<uint8_t> sessionLimit)
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +053060{
61 uint8_t sessLimit = sessionLimit.value_or(0);
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +000062 if (reserved1 || reserved2 || sessLimit ||
63 !ipmiUserIsValidPrivilege(static_cast<uint8_t>(privilege)))
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +053064 {
George Liu82844ef2024-07-17 17:03:56 +080065 lg2::debug("Set user access - Invalid field in request");
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +053066 return ipmi::responseInvalidFieldRequest();
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +053067 }
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +000068
Patrick Williams1318a5e2024-08-16 15:19:54 -040069 uint8_t chNum =
70 convertCurrentChannelNum(static_cast<uint8_t>(channel), ctx->channel);
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +000071 if (!isValidChannel(chNum))
72 {
George Liu82844ef2024-07-17 17:03:56 +080073 lg2::debug("Set user access - Invalid channel request");
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +000074 return ipmi::response(invalidChannel);
75 }
76 if (getChannelSessionSupport(chNum) == EChannelSessSupported::none)
77 {
George Liu82844ef2024-07-17 17:03:56 +080078 lg2::debug("Set user access - No support on channel");
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +000079 return ipmi::response(ccActionNotSupportedForChannel);
80 }
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +053081 if (!ipmiUserIsValidUserId(static_cast<uint8_t>(userId)))
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +053082 {
George Liu82844ef2024-07-17 17:03:56 +080083 lg2::debug("Set user access - Parameter out of range");
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +053084 return ipmi::responseParmOutOfRange();
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +053085 }
Richard Marian Thomaiyar06df8762018-12-08 17:38:25 +053086
Willy Tu11d68892022-01-20 10:37:34 -080087 PrivAccess privAccess = {};
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +053088 if (bitsUpdate)
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +053089 {
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +053090 privAccess.ipmiEnabled = static_cast<uint8_t>(ipmiEnabled);
91 privAccess.linkAuthEnabled = static_cast<uint8_t>(linkAuthEnabled);
92 privAccess.accessCallback = static_cast<uint8_t>(accessCallback);
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +053093 }
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +053094 privAccess.privilege = static_cast<uint8_t>(privilege);
95 return ipmi::response(
96 ipmiUserSetPrivilegeAccess(static_cast<uint8_t>(userId), chNum,
97 privAccess, static_cast<bool>(bitsUpdate)));
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +053098}
99
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530100/** @brief implements the set user access command
101 * @param ctx - IPMI context pointer (for channel)
102 * @param channel - channel number
103 * @param reserved1 - skip 4 bits
104 * @param userId - user id
105 * @param reserved2 - skip 2 bits
106 *
107 * @returns ipmi completion code plus response data
108 * - maxChUsers - max channel users
109 * - reserved1 - skip 2 bits
110 * - enabledUsers - enabled users count
111 * - enabledStatus - enabled status
112 * - fixedUsers - fixed users count
113 * - reserved2 - skip 2 bits
114 * - privilege - user privilege
115 * - ipmiEnabled - ipmi messaging state
116 * - linkAuthEnabled - link authenticatin state
117 * - accessCallback - callback state
118 * - reserved - skip 1 bit
119 */
120ipmi::RspType<uint6_t, // max channel users
121 uint2_t, // reserved1
122
123 uint6_t, // enabled users count
124 uint2_t, // enabled status
125
126 uint6_t, // fixed users count
127 uint2_t, // reserved2
128
129 uint4_t, // privilege
130 uint1_t, // ipmi messaging state
131 uint1_t, // link authentication state
132 uint1_t, // access callback state
133 uint1_t // reserved3
134 >
135 ipmiGetUserAccess(ipmi::Context::ptr ctx, uint4_t channel,
136 uint4_t reserved1,
137
138 uint6_t userId, uint2_t reserved2)
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530139{
Patrick Williams1318a5e2024-08-16 15:19:54 -0400140 uint8_t chNum =
141 convertCurrentChannelNum(static_cast<uint8_t>(channel), ctx->channel);
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +0000142
143 if (reserved1 || reserved2 || !isValidChannel(chNum))
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530144 {
George Liu82844ef2024-07-17 17:03:56 +0800145 lg2::debug("Get user access - Invalid field in request");
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530146 return ipmi::responseInvalidFieldRequest();
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530147 }
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +0000148
149 if (getChannelSessionSupport(chNum) == EChannelSessSupported::none)
150 {
George Liu82844ef2024-07-17 17:03:56 +0800151 lg2::debug("Get user access - No support on channel");
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +0000152 return ipmi::response(ccActionNotSupportedForChannel);
153 }
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530154 if (!ipmiUserIsValidUserId(static_cast<uint8_t>(userId)))
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530155 {
George Liu82844ef2024-07-17 17:03:56 +0800156 lg2::debug("Get user access - Parameter out of range");
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530157 return ipmi::responseParmOutOfRange();
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530158 }
159
160 uint8_t maxChUsers = 0, enabledUsers = 0, fixedUsers = 0;
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530161 ipmi::Cc retStatus;
Richard Marian Thomaiyarb6771e02019-01-29 14:42:44 +0530162 retStatus = ipmiUserGetAllCounts(maxChUsers, enabledUsers, fixedUsers);
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000163 if (retStatus != ccSuccess)
Richard Marian Thomaiyarb6771e02019-01-29 14:42:44 +0530164 {
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530165 return ipmi::response(retStatus);
Richard Marian Thomaiyarb6771e02019-01-29 14:42:44 +0530166 }
167
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530168 bool enabledState = false;
Patrick Williams1318a5e2024-08-16 15:19:54 -0400169 retStatus =
170 ipmiUserCheckEnabled(static_cast<uint8_t>(userId), enabledState);
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000171 if (retStatus != ccSuccess)
Richard Marian Thomaiyarb6771e02019-01-29 14:42:44 +0530172 {
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530173 return ipmi::response(retStatus);
Richard Marian Thomaiyarb6771e02019-01-29 14:42:44 +0530174 }
175
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530176 uint2_t enabledStatus = enabledState ? userIdEnabledViaSetPassword
177 : userIdDisabledViaSetPassword;
178 PrivAccess privAccess{};
179 retStatus = ipmiUserGetPrivilegeAccess(static_cast<uint8_t>(userId), chNum,
180 privAccess);
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000181 if (retStatus != ccSuccess)
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530182 {
183 return ipmi::response(retStatus);
184 }
185 constexpr uint2_t res2Bits = 0;
186 return ipmi::responseSuccess(
187 static_cast<uint6_t>(maxChUsers), res2Bits,
188
189 static_cast<uint6_t>(enabledUsers), enabledStatus,
190
191 static_cast<uint6_t>(fixedUsers), res2Bits,
192
193 static_cast<uint4_t>(privAccess.privilege),
194 static_cast<uint1_t>(privAccess.ipmiEnabled),
195 static_cast<uint1_t>(privAccess.linkAuthEnabled),
196 static_cast<uint1_t>(privAccess.accessCallback),
197 static_cast<uint1_t>(privAccess.reserved));
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530198}
199
Vernon Maueryac30b392021-08-05 11:08:23 -0700200/** @brief implementes the get user name command
201 * @param[in] ctx - ipmi command context
202 * @param[in] userId - 6-bit user ID
203 * @param[in] reserved - 2-bits reserved
204 * @param[in] name - 16-byte array for username
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530205
Vernon Maueryac30b392021-08-05 11:08:23 -0700206 * @returns ipmi response
207 */
Patrick Williams1318a5e2024-08-16 15:19:54 -0400208ipmi::RspType<> ipmiSetUserName(
209 [[maybe_unused]] ipmi::Context::ptr ctx, uint6_t id, uint2_t reserved,
210 const std::array<uint8_t, ipmi::ipmiMaxUserName>& name)
Vernon Maueryac30b392021-08-05 11:08:23 -0700211{
212 if (reserved)
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530213 {
Vernon Maueryac30b392021-08-05 11:08:23 -0700214 return ipmi::responseInvalidFieldRequest();
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530215 }
Vernon Maueryac30b392021-08-05 11:08:23 -0700216 uint8_t userId = static_cast<uint8_t>(id);
217 if (!ipmiUserIsValidUserId(userId))
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530218 {
George Liu82844ef2024-07-17 17:03:56 +0800219 lg2::debug("Set user name - Invalid user id");
Vernon Maueryac30b392021-08-05 11:08:23 -0700220 return ipmi::responseParmOutOfRange();
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530221 }
222
Vernon Maueryac30b392021-08-05 11:08:23 -0700223 size_t nameLen = strnlen(reinterpret_cast<const char*>(name.data()),
224 ipmi::ipmiMaxUserName);
225 const std::string strUserName(reinterpret_cast<const char*>(name.data()),
jayaprakash Mutyalacdcdf2b2020-03-28 00:12:05 +0000226 nameLen);
227
Vernon Maueryac30b392021-08-05 11:08:23 -0700228 ipmi::Cc res = ipmiUserSetUserName(userId, strUserName);
229 return ipmi::response(res);
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530230}
231
232/** @brief implementes the get user name command
Vernon Mauery3c89de12021-08-05 11:08:23 -0700233 * @param[in] ctx - ipmi command context
234 * @param[in] userId - 6-bit user ID
235 * @param[in] reserved - 2-bits reserved
236
237 * @returns ipmi response with 16-byte username
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530238 */
Vernon Mauery3c89de12021-08-05 11:08:23 -0700239ipmi::RspType<std::array<uint8_t, ipmi::ipmiMaxUserName>> // user name
Willy Tu11d68892022-01-20 10:37:34 -0800240 ipmiGetUserName([[maybe_unused]] ipmi::Context::ptr ctx, uint6_t id,
241 uint2_t reserved)
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530242{
Vernon Mauery3c89de12021-08-05 11:08:23 -0700243 if (reserved)
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530244 {
Vernon Mauery3c89de12021-08-05 11:08:23 -0700245 return ipmi::responseInvalidFieldRequest();
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530246 }
247
Vernon Mauery3c89de12021-08-05 11:08:23 -0700248 uint8_t userId = static_cast<uint8_t>(id);
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530249 std::string userName;
Vernon Mauery3c89de12021-08-05 11:08:23 -0700250 if (ipmiUserGetUserName(userId, userName) != ccSuccess)
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530251 { // Invalid User ID
George Liu82844ef2024-07-17 17:03:56 +0800252 lg2::debug("User Name not found, user Id: {USER_ID}", "USER_ID",
253 userId);
Vernon Mauery3c89de12021-08-05 11:08:23 -0700254 return ipmi::responseParmOutOfRange();
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530255 }
Vernon Mauery3c89de12021-08-05 11:08:23 -0700256 // copy the std::string into a fixed array
257 if (userName.size() > ipmi::ipmiMaxUserName)
258 {
259 return ipmi::responseUnspecifiedError();
260 }
261 std::array<uint8_t, ipmi::ipmiMaxUserName> userNameFixed;
262 std::fill(userNameFixed.begin(), userNameFixed.end(), 0);
263 std::copy(userName.begin(), userName.end(), userNameFixed.begin());
264 return ipmi::responseSuccess(std::move(userNameFixed));
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530265}
266
Vernon Mauery7a3296d2021-08-05 11:08:23 -0700267/** @brief implementes the get user name command
268 * @param[in] ctx - ipmi command context
269 * @param[in] userId - 6-bit user ID
270 * @param[in] reserved - 2-bits reserved
271
272 * @returns ipmi response with 16-byte username
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530273 */
Vernon Mauery7a3296d2021-08-05 11:08:23 -0700274ipmi::RspType<> // user name
Willy Tu11d68892022-01-20 10:37:34 -0800275 ipmiSetUserPassword([[maybe_unused]] ipmi::Context::ptr ctx, uint6_t id,
276 bool reserved1, bool pwLen20, uint2_t operation,
277 uint6_t reserved2, SecureBuffer& userPassword)
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530278{
Vernon Mauery7a3296d2021-08-05 11:08:23 -0700279 if (reserved1 || reserved2)
Snehalatha Venkatesh37b1d1a2021-06-28 10:13:37 +0000280 {
George Liu82844ef2024-07-17 17:03:56 +0800281 lg2::debug("Invalid data field in request");
Vernon Mauery7a3296d2021-08-05 11:08:23 -0700282 return ipmi::responseInvalidFieldRequest();
Snehalatha Venkatesh37b1d1a2021-06-28 10:13:37 +0000283 }
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530284
Ayushi Smriti29b9f312021-09-24 12:29:23 +0530285 static constexpr uint2_t opDisableUser = 0x00;
286 static constexpr uint2_t opEnableUser = 0x01;
287 static constexpr uint2_t opSetPassword = 0x02;
288 static constexpr uint2_t opTestPassword = 0x03;
289
290 // If set / test password operation then password size has to be 16 or 20
291 // bytes based on the password size bit
292 if (((operation == opSetPassword) || (operation == opTestPassword)) &&
293 ((pwLen20 && (userPassword.size() != maxIpmi20PasswordSize)) ||
294 (!pwLen20 && (userPassword.size() != maxIpmi15PasswordSize))))
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530295 {
George Liu82844ef2024-07-17 17:03:56 +0800296 lg2::debug("Invalid Length");
Vernon Mauery7a3296d2021-08-05 11:08:23 -0700297 return ipmi::responseReqDataLenInvalid();
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530298 }
Ayushi Smriti29b9f312021-09-24 12:29:23 +0530299
Vernon Mauery7a3296d2021-08-05 11:08:23 -0700300 size_t passwordLength = userPassword.size();
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530301
Vernon Mauery7a3296d2021-08-05 11:08:23 -0700302 uint8_t userId = static_cast<uint8_t>(id);
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530303 std::string userName;
Vernon Mauery7a3296d2021-08-05 11:08:23 -0700304 if (ipmiUserGetUserName(userId, userName) != ccSuccess)
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530305 {
George Liu82844ef2024-07-17 17:03:56 +0800306 lg2::debug("User Name not found, user Id: {USER_ID}", "USER_ID",
307 userId);
Vernon Mauery7a3296d2021-08-05 11:08:23 -0700308 return ipmi::responseParmOutOfRange();
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530309 }
Vernon Mauery7a3296d2021-08-05 11:08:23 -0700310
Vernon Mauery7a3296d2021-08-05 11:08:23 -0700311 if (operation == opSetPassword)
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530312 {
Vernon Mauery7a3296d2021-08-05 11:08:23 -0700313 // turn the non-nul terminated SecureBuffer into a SecureString
314 SecureString password(
315 reinterpret_cast<const char*>(userPassword.data()), passwordLength);
316 ipmi::Cc res = ipmiUserSetUserPassword(userId, password.data());
317 return ipmi::response(res);
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530318 }
Vernon Mauery7a3296d2021-08-05 11:08:23 -0700319 else if (operation == opEnableUser || operation == opDisableUser)
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530320 {
Patrick Williams1318a5e2024-08-16 15:19:54 -0400321 ipmi::Cc res =
322 ipmiUserUpdateEnabledState(userId, static_cast<bool>(operation));
Vernon Mauery7a3296d2021-08-05 11:08:23 -0700323 return ipmi::response(res);
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530324 }
Vernon Mauery7a3296d2021-08-05 11:08:23 -0700325 else if (operation == opTestPassword)
Richard Marian Thomaiyar282e79b2018-11-13 19:00:58 +0530326 {
Vernon Mauery1e22a0f2021-07-30 13:36:54 -0700327 SecureString password = ipmiUserGetPassword(userName);
Vernon Mauery7a3296d2021-08-05 11:08:23 -0700328 // extend with zeros, if needed
329 if (password.size() < passwordLength)
330 {
331 password.resize(passwordLength, '\0');
332 }
Vernon Mauery1e22a0f2021-07-30 13:36:54 -0700333 SecureString testPassword(
Vernon Mauery7a3296d2021-08-05 11:08:23 -0700334 reinterpret_cast<const char*>(userPassword.data()), passwordLength);
Vernon Mauery1e22a0f2021-07-30 13:36:54 -0700335 // constant time string compare: always compare exactly as many bytes
336 // as the length of the input, resizing the actual password to match,
337 // maintaining a knowledge if the sizes differed originally
338 static const std::array<char, maxIpmi20PasswordSize> empty = {'\0'};
339 size_t cmpLen = testPassword.size();
340 bool pwLenDiffers = password.size() != cmpLen;
341 const char* cmpPassword = nullptr;
342 if (pwLenDiffers)
343 {
344 cmpPassword = empty.data();
345 }
346 else
347 {
348 cmpPassword = password.data();
349 }
350 bool pwBad = CRYPTO_memcmp(cmpPassword, testPassword.data(), cmpLen);
351 pwBad |= pwLenDiffers;
352 if (pwBad)
Richard Marian Thomaiyar282e79b2018-11-13 19:00:58 +0530353 {
George Liu82844ef2024-07-17 17:03:56 +0800354 lg2::debug("Test password failed, user Id: {USER_ID}", "USER_ID",
355 userId);
Vernon Mauery7a3296d2021-08-05 11:08:23 -0700356 return ipmi::response(ipmiCCPasswdFailMismatch);
Richard Marian Thomaiyar282e79b2018-11-13 19:00:58 +0530357 }
Vernon Mauery7a3296d2021-08-05 11:08:23 -0700358 return ipmi::responseSuccess();
Richard Marian Thomaiyar282e79b2018-11-13 19:00:58 +0530359 }
Vernon Mauery7a3296d2021-08-05 11:08:23 -0700360 return ipmi::responseInvalidFieldRequest();
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530361}
362
smritic46f6cd2019-03-20 14:09:41 +0530363/** @brief implements the get channel authentication command
364 * @param ctx - IPMI context pointer (for channel)
365 * @param extData - get IPMI 2.0 extended data
366 * @param reserved1 - skip 3 bits
367 * @param chNum - channel number to get info about
368 * @param reserved2 - skip 4 bits
369 * @param privLevel - requested privilege level
370
371 * @returns ipmi completion code plus response data
372 * - channel number
373 * - rmcpAuthTypes - RMCP auth types (IPMI 1.5)
374 * - reserved1
375 * - extDataSupport - true for IPMI 2.0 extensions
376 * - anonymousLogin - true for anonymous login enabled
377 * - nullUsers - true for null user names enabled
378 * - nonNullUsers - true for non-null usernames enabled
379 * - userAuth - false for user authentication enabled
380 * - perMessageAuth - false for per message authentication enabled
381 * - KGStatus - true for Kg required for authentication
382 * - reserved2
383 * - rmcp - RMCP (IPMI 1.5) connection support
384 * - rmcpp - RMCP+ (IPMI 2.0) connection support
385 * - reserved3
386 * - oemID - OEM IANA of any OEM auth support
387 * - oemAuxillary - OEM data for auth
388 */
389ipmi::RspType<uint8_t, // channel number
390 uint6_t, // rmcpAuthTypes
391 bool, // reserved1
392 bool, // extDataSupport
393 bool, // anonymousLogin
394 bool, // nullUsers
395 bool, // nonNullUsers
396 bool, // userAuth
397 bool, // perMessageAuth
398 bool, // KGStatus
399 uint2_t, // reserved2
400 bool, // rmcp
401 bool, // rmcpp
402 uint6_t, // reserved3
403 uint24_t, // oemID
404 uint8_t // oemAuxillary
405 >
Patrick Williams1318a5e2024-08-16 15:19:54 -0400406 ipmiGetChannelAuthenticationCapabilities(
407 ipmi::Context::ptr ctx, uint4_t chNum, uint3_t reserved1,
408 [[maybe_unused]] bool extData, uint4_t privLevel, uint4_t reserved2)
smritic46f6cd2019-03-20 14:09:41 +0530409{
Patrick Williams1318a5e2024-08-16 15:19:54 -0400410 uint8_t channel =
411 convertCurrentChannelNum(static_cast<uint8_t>(chNum), ctx->channel);
smritic46f6cd2019-03-20 14:09:41 +0530412
413 if (reserved1 || reserved2 || !isValidChannel(channel) ||
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +0000414 !isValidPrivLimit(static_cast<uint8_t>(privLevel)))
smritic46f6cd2019-03-20 14:09:41 +0530415 {
George Liu82844ef2024-07-17 17:03:56 +0800416 lg2::debug("Get channel auth capabilities - Invalid field in request");
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +0000417 return ipmi::responseInvalidFieldRequest();
418 }
419
420 if (getChannelSessionSupport(channel) == EChannelSessSupported::none)
421 {
George Liu82844ef2024-07-17 17:03:56 +0800422 lg2::debug("Get channel auth capabilities - No support on channel");
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +0000423 return ipmi::response(ccActionNotSupportedForChannel);
smritic46f6cd2019-03-20 14:09:41 +0530424 }
425
426 constexpr bool extDataSupport = true; // true for IPMI 2.0 extensions
427 constexpr bool reserved3 = false;
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -0500428 constexpr uint6_t rmcpAuthTypes = 0; // IPMI 1.5 auth types - not supported
smritic46f6cd2019-03-20 14:09:41 +0530429 constexpr uint2_t reserved4 = 0;
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -0500430 constexpr bool KGStatus = false; // Not supporting now.
smritic46f6cd2019-03-20 14:09:41 +0530431 constexpr bool perMessageAuth = false; // Per message auth - enabled
432 constexpr bool userAuth = false; // User authentication - enabled
433 constexpr bool nullUsers = false; // Null user names - not supported
434 constexpr bool anonymousLogin = false; // Anonymous login - not supported
435 constexpr uint6_t reserved5 = 0;
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -0500436 constexpr bool rmcpp = true; // IPMI 2.0 - supported
437 constexpr bool rmcp = false; // IPMI 1.5 - not supported
smritic46f6cd2019-03-20 14:09:41 +0530438 constexpr uint24_t oemID = 0;
439 constexpr uint8_t oemAuxillary = 0;
440
441 bool nonNullUsers = 0;
442 uint8_t maxChUsers = 0, enabledUsers = 0, fixedUsers = 0;
443 ipmi::ipmiUserGetAllCounts(maxChUsers, enabledUsers, fixedUsers);
444 nonNullUsers = enabledUsers > 0;
445
446 return ipmi::responseSuccess(
447 channel, rmcpAuthTypes, reserved3, extDataSupport, anonymousLogin,
448 nullUsers, nonNullUsers, userAuth, perMessageAuth, KGStatus, reserved4,
449 rmcp, rmcpp, reserved5, oemID, oemAuxillary);
450}
451
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000452/** @brief implements the set user payload access command.
453 * @param ctx - IPMI context pointer (for channel)
454 * @param channel - channel number (4 bits)
455 * @param reserved1 - skip 4 bits
456 * @param userId - user id (6 bits)
457 * @param operation - access ENABLE /DISABLE. (2 bits)
458 * @param stdPayload0 - IPMI - reserved. (1 bit)
459 * @param stdPayload1 - SOL. (1 bit)
460 * @param stdPayload2 - (1 bit)
461 * @param stdPayload3 - (1 bit)
462 * @param stdPayload4 - (1 bit)
463 * @param stdPayload5 - (1 bit)
464 * @param stdPayload6 - (1 bit)
465 * @param stdPayload7 - (1 bit)
466 * @param stdPayloadEnables2Reserved - (8 bits)
467 * @param oemPayload0 - (1 bit)
468 * @param oemPayload1 - (1 bit)
469 * @param oemPayload2 - (1 bit)
470 * @param oemPayload3 - (1 bit)
471 * @param oemPayload4 - (1 bit)
472 * @param oemPayload5 - (1 bit)
473 * @param oemPayload6 - (1 bit)
474 * @param oemPayload7 - (1 bit)
475 * @param oemPayloadEnables2Reserved - (8 bits)
476 *
477 * @returns IPMI completion code
478 */
479ipmi::RspType<> ipmiSetUserPayloadAccess(
480 ipmi::Context::ptr ctx,
481
482 uint4_t channel, uint4_t reserved,
483
484 uint6_t userId, uint2_t operation,
485
486 bool stdPayload0ipmiReserved, bool stdPayload1SOL, bool stdPayload2,
487 bool stdPayload3, bool stdPayload4, bool stdPayload5, bool stdPayload6,
488 bool stdPayload7,
489
490 uint8_t stdPayloadEnables2Reserved,
491
492 bool oemPayload0, bool oemPayload1, bool oemPayload2, bool oemPayload3,
493 bool oemPayload4, bool oemPayload5, bool oemPayload6, bool oemPayload7,
494
495 uint8_t oemPayloadEnables2Reserved)
496{
Patrick Williams1318a5e2024-08-16 15:19:54 -0400497 auto chNum =
498 convertCurrentChannelNum(static_cast<uint8_t>(channel), ctx->channel);
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000499 // Validate the reserved args. Only SOL payload is supported as on date.
500 if (reserved || stdPayload0ipmiReserved || stdPayload2 || stdPayload3 ||
501 stdPayload4 || stdPayload5 || stdPayload6 || stdPayload7 ||
502 oemPayload0 || oemPayload1 || oemPayload2 || oemPayload3 ||
503 oemPayload4 || oemPayload5 || oemPayload6 || oemPayload7 ||
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +0000504 stdPayloadEnables2Reserved || oemPayloadEnables2Reserved ||
505 !isValidChannel(chNum))
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000506 {
507 return ipmi::responseInvalidFieldRequest();
508 }
509
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +0000510 if ((operation != enableOperation && operation != disableOperation))
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000511 {
512 return ipmi::responseInvalidFieldRequest();
513 }
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +0000514 if (getChannelSessionSupport(chNum) == EChannelSessSupported::none)
515 {
516 return ipmi::response(ccActionNotSupportedForChannel);
517 }
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000518 if (!ipmiUserIsValidUserId(static_cast<uint8_t>(userId)))
519 {
520 return ipmi::responseParmOutOfRange();
521 }
522
Willy Tu11d68892022-01-20 10:37:34 -0800523 PayloadAccess payloadAccess = {};
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000524 payloadAccess.stdPayloadEnables1[1] = stdPayload1SOL;
525
526 return ipmi::response(ipmiUserSetUserPayloadAccess(
527 chNum, static_cast<uint8_t>(operation), static_cast<uint8_t>(userId),
528 payloadAccess));
529}
530
531/** @brief implements the get user payload access command
532 * This command returns information about user payload enable settings
533 * that were set using the 'Set User Payload Access' Command.
534 *
535 * @param ctx - IPMI context pointer (for channel)
536 * @param channel - channel number
537 * @param reserved1 - skip 4 bits
538 * @param userId - user id
539 * @param reserved2 - skip 2 bits
540 *
541 * @returns IPMI completion code plus response data
542 * - stdPayload0ipmiReserved - IPMI payload (reserved).
543 * - stdPayload1SOL - SOL payload
544 * - stdPayload2
545 * - stdPayload3
546 * - stdPayload4
547 * - stdPayload5
548 * - stdPayload6
549 * - stdPayload7
550
551 * - stdPayloadEnables2Reserved - Reserved.
552
553 * - oemPayload0
554 * - oemPayload1
555 * - oemPayload2
556 * - oemPayload3
557 * - oemPayload4
558 * - oemPayload5
559 * - oemPayload6
560 * - oemPayload7
561
562 * - oemPayloadEnables2Reserved - Reserved
563 */
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -0500564ipmi::RspType<bool, // stdPayload0ipmiReserved
565 bool, // stdPayload1SOL
566 bool, // stdPayload2
567 bool, // stdPayload3
568 bool, // stdPayload4
569 bool, // stdPayload5
570 bool, // stdPayload6
571 bool, // stdPayload7
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000572
573 uint8_t, // stdPayloadEnables2Reserved
574
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -0500575 bool, // oemPayload0
576 bool, // oemPayload1
577 bool, // oemPayload2
578 bool, // oemPayload3
579 bool, // oemPayload4
580 bool, // oemPayload5
581 bool, // oemPayload6
582 bool, // oemPayload7
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000583
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -0500584 uint8_t // oemPayloadEnables2Reserved
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000585 >
586 ipmiGetUserPayloadAccess(ipmi::Context::ptr ctx,
587
588 uint4_t channel, uint4_t reserved1,
589
590 uint6_t userId, uint2_t reserved2)
591{
Patrick Williams1318a5e2024-08-16 15:19:54 -0400592 uint8_t chNum =
593 convertCurrentChannelNum(static_cast<uint8_t>(channel), ctx->channel);
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +0000594
595 if (reserved1 || reserved2 || !isValidChannel(chNum))
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000596 {
597 return ipmi::responseInvalidFieldRequest();
598 }
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +0000599 if (getChannelSessionSupport(chNum) == EChannelSessSupported::none)
600 {
601 return ipmi::response(ccActionNotSupportedForChannel);
602 }
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000603 if (!ipmiUserIsValidUserId(static_cast<uint8_t>(userId)))
604 {
605 return ipmi::responseParmOutOfRange();
606 }
607
608 ipmi::Cc retStatus;
609 PayloadAccess payloadAccess = {};
610 retStatus = ipmiUserGetUserPayloadAccess(
611 chNum, static_cast<uint8_t>(userId), payloadAccess);
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000612 if (retStatus != ccSuccess)
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000613 {
614 return ipmi::response(retStatus);
615 }
616 constexpr uint8_t res8bits = 0;
Patrick Williams1318a5e2024-08-16 15:19:54 -0400617 return ipmi::responseSuccess(
618 payloadAccess.stdPayloadEnables1.test(0),
619 payloadAccess.stdPayloadEnables1.test(1),
620 payloadAccess.stdPayloadEnables1.test(2),
621 payloadAccess.stdPayloadEnables1.test(3),
622 payloadAccess.stdPayloadEnables1.test(4),
623 payloadAccess.stdPayloadEnables1.test(5),
624 payloadAccess.stdPayloadEnables1.test(6),
625 payloadAccess.stdPayloadEnables1.test(7),
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000626
Patrick Williams1318a5e2024-08-16 15:19:54 -0400627 res8bits,
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000628
Patrick Williams1318a5e2024-08-16 15:19:54 -0400629 payloadAccess.oemPayloadEnables1.test(0),
630 payloadAccess.oemPayloadEnables1.test(1),
631 payloadAccess.oemPayloadEnables1.test(2),
632 payloadAccess.oemPayloadEnables1.test(3),
633 payloadAccess.oemPayloadEnables1.test(4),
634 payloadAccess.oemPayloadEnables1.test(5),
635 payloadAccess.oemPayloadEnables1.test(6),
636 payloadAccess.oemPayloadEnables1.test(7),
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000637
Patrick Williams1318a5e2024-08-16 15:19:54 -0400638 res8bits);
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000639}
640
William A. Kennington III343d0612018-12-10 15:56:24 -0800641void registerUserIpmiFunctions() __attribute__((constructor));
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530642void registerUserIpmiFunctions()
643{
Richard Marian Thomaiyar0be80bd2020-01-10 12:20:16 +0530644 post_work([]() { ipmiUserInit(); });
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530645 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
646 ipmi::app::cmdSetUserAccessCommand,
647 ipmi::Privilege::Admin, ipmiSetUserAccess);
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530648
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530649 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
650 ipmi::app::cmdGetUserAccessCommand,
ankita prasadbd604762023-01-18 10:56:43 +0000651 ipmi::Privilege::Admin, ipmiGetUserAccess);
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530652
Vernon Mauery3c89de12021-08-05 11:08:23 -0700653 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
654 ipmi::app::cmdGetUserNameCommand,
ankita prasadbd604762023-01-18 10:56:43 +0000655 ipmi::Privilege::Admin, ipmiGetUserName);
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530656
Vernon Maueryac30b392021-08-05 11:08:23 -0700657 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
658 ipmi::app::cmdSetUserName, ipmi::Privilege::Admin,
659 ipmiSetUserName);
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530660
Vernon Mauery7a3296d2021-08-05 11:08:23 -0700661 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
662 ipmi::app::cmdSetUserPasswordCommand,
663 ipmi::Privilege::Admin, ipmiSetUserPassword);
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530664
smritic46f6cd2019-03-20 14:09:41 +0530665 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
666 ipmi::app::cmdGetChannelAuthCapabilities,
667 ipmi::Privilege::Callback,
668 ipmiGetChannelAuthenticationCapabilities);
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000669
670 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
671 ipmi::app::cmdSetUserPayloadAccess,
672 ipmi::Privilege::Admin, ipmiSetUserPayloadAccess);
673
674 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
675 ipmi::app::cmdGetUserPayloadAccess,
676 ipmi::Privilege::Operator, ipmiGetUserPayloadAccess);
677
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530678 return;
679}
680} // namespace ipmi