blob: 53b34f8332b2d02e93ae37d1f26fdca441d7f4b9 [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 */
51ipmi::RspType<> ipmiSetUserAccess(ipmi::Context::ptr ctx, uint4_t channel,
52 uint1_t ipmiEnabled, uint1_t linkAuthEnabled,
53 uint1_t accessCallback, uint1_t bitsUpdate,
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +053054
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +053055 uint6_t userId, uint2_t reserved1,
56
57 uint4_t privilege, uint4_t reserved2,
58
59 std::optional<uint8_t> sessionLimit)
60{
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 Williamsfbc6c9d2023-05-10 07:50:16 -050069 uint8_t chNum = convertCurrentChannelNum(static_cast<uint8_t>(channel),
70 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 Williamsfbc6c9d2023-05-10 07:50:16 -0500140 uint8_t chNum = convertCurrentChannelNum(static_cast<uint8_t>(channel),
141 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 Williamsfbc6c9d2023-05-10 07:50:16 -0500169 retStatus = ipmiUserCheckEnabled(static_cast<uint8_t>(userId),
170 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 */
208ipmi::RspType<>
Willy Tu11d68892022-01-20 10:37:34 -0800209 ipmiSetUserName([[maybe_unused]] ipmi::Context::ptr ctx, uint6_t id,
210 uint2_t reserved,
Vernon Maueryac30b392021-08-05 11:08:23 -0700211 const std::array<uint8_t, ipmi::ipmiMaxUserName>& name)
212{
213 if (reserved)
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530214 {
Vernon Maueryac30b392021-08-05 11:08:23 -0700215 return ipmi::responseInvalidFieldRequest();
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530216 }
Vernon Maueryac30b392021-08-05 11:08:23 -0700217 uint8_t userId = static_cast<uint8_t>(id);
218 if (!ipmiUserIsValidUserId(userId))
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530219 {
George Liu82844ef2024-07-17 17:03:56 +0800220 lg2::debug("Set user name - Invalid user id");
Vernon Maueryac30b392021-08-05 11:08:23 -0700221 return ipmi::responseParmOutOfRange();
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530222 }
223
Vernon Maueryac30b392021-08-05 11:08:23 -0700224 size_t nameLen = strnlen(reinterpret_cast<const char*>(name.data()),
225 ipmi::ipmiMaxUserName);
226 const std::string strUserName(reinterpret_cast<const char*>(name.data()),
jayaprakash Mutyalacdcdf2b2020-03-28 00:12:05 +0000227 nameLen);
228
Vernon Maueryac30b392021-08-05 11:08:23 -0700229 ipmi::Cc res = ipmiUserSetUserName(userId, strUserName);
230 return ipmi::response(res);
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530231}
232
233/** @brief implementes the get user name command
Vernon Mauery3c89de12021-08-05 11:08:23 -0700234 * @param[in] ctx - ipmi command context
235 * @param[in] userId - 6-bit user ID
236 * @param[in] reserved - 2-bits reserved
237
238 * @returns ipmi response with 16-byte username
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530239 */
Vernon Mauery3c89de12021-08-05 11:08:23 -0700240ipmi::RspType<std::array<uint8_t, ipmi::ipmiMaxUserName>> // user name
Willy Tu11d68892022-01-20 10:37:34 -0800241 ipmiGetUserName([[maybe_unused]] ipmi::Context::ptr ctx, uint6_t id,
242 uint2_t reserved)
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530243{
Vernon Mauery3c89de12021-08-05 11:08:23 -0700244 if (reserved)
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530245 {
Vernon Mauery3c89de12021-08-05 11:08:23 -0700246 return ipmi::responseInvalidFieldRequest();
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530247 }
248
Vernon Mauery3c89de12021-08-05 11:08:23 -0700249 uint8_t userId = static_cast<uint8_t>(id);
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530250 std::string userName;
Vernon Mauery3c89de12021-08-05 11:08:23 -0700251 if (ipmiUserGetUserName(userId, userName) != ccSuccess)
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530252 { // Invalid User ID
George Liu82844ef2024-07-17 17:03:56 +0800253 lg2::debug("User Name not found, user Id: {USER_ID}", "USER_ID",
254 userId);
Vernon Mauery3c89de12021-08-05 11:08:23 -0700255 return ipmi::responseParmOutOfRange();
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530256 }
Vernon Mauery3c89de12021-08-05 11:08:23 -0700257 // copy the std::string into a fixed array
258 if (userName.size() > ipmi::ipmiMaxUserName)
259 {
260 return ipmi::responseUnspecifiedError();
261 }
262 std::array<uint8_t, ipmi::ipmiMaxUserName> userNameFixed;
263 std::fill(userNameFixed.begin(), userNameFixed.end(), 0);
264 std::copy(userName.begin(), userName.end(), userNameFixed.begin());
265 return ipmi::responseSuccess(std::move(userNameFixed));
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530266}
267
Vernon Mauery7a3296d2021-08-05 11:08:23 -0700268/** @brief implementes the get user name command
269 * @param[in] ctx - ipmi command context
270 * @param[in] userId - 6-bit user ID
271 * @param[in] reserved - 2-bits reserved
272
273 * @returns ipmi response with 16-byte username
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530274 */
Vernon Mauery7a3296d2021-08-05 11:08:23 -0700275ipmi::RspType<> // user name
Willy Tu11d68892022-01-20 10:37:34 -0800276 ipmiSetUserPassword([[maybe_unused]] ipmi::Context::ptr ctx, uint6_t id,
277 bool reserved1, bool pwLen20, uint2_t operation,
278 uint6_t reserved2, SecureBuffer& userPassword)
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530279{
Vernon Mauery7a3296d2021-08-05 11:08:23 -0700280 if (reserved1 || reserved2)
Snehalatha Venkatesh37b1d1a2021-06-28 10:13:37 +0000281 {
George Liu82844ef2024-07-17 17:03:56 +0800282 lg2::debug("Invalid data field in request");
Vernon Mauery7a3296d2021-08-05 11:08:23 -0700283 return ipmi::responseInvalidFieldRequest();
Snehalatha Venkatesh37b1d1a2021-06-28 10:13:37 +0000284 }
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530285
Ayushi Smriti29b9f312021-09-24 12:29:23 +0530286 static constexpr uint2_t opDisableUser = 0x00;
287 static constexpr uint2_t opEnableUser = 0x01;
288 static constexpr uint2_t opSetPassword = 0x02;
289 static constexpr uint2_t opTestPassword = 0x03;
290
291 // If set / test password operation then password size has to be 16 or 20
292 // bytes based on the password size bit
293 if (((operation == opSetPassword) || (operation == opTestPassword)) &&
294 ((pwLen20 && (userPassword.size() != maxIpmi20PasswordSize)) ||
295 (!pwLen20 && (userPassword.size() != maxIpmi15PasswordSize))))
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530296 {
George Liu82844ef2024-07-17 17:03:56 +0800297 lg2::debug("Invalid Length");
Vernon Mauery7a3296d2021-08-05 11:08:23 -0700298 return ipmi::responseReqDataLenInvalid();
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530299 }
Ayushi Smriti29b9f312021-09-24 12:29:23 +0530300
Vernon Mauery7a3296d2021-08-05 11:08:23 -0700301 size_t passwordLength = userPassword.size();
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530302
Vernon Mauery7a3296d2021-08-05 11:08:23 -0700303 uint8_t userId = static_cast<uint8_t>(id);
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530304 std::string userName;
Vernon Mauery7a3296d2021-08-05 11:08:23 -0700305 if (ipmiUserGetUserName(userId, userName) != ccSuccess)
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530306 {
George Liu82844ef2024-07-17 17:03:56 +0800307 lg2::debug("User Name not found, user Id: {USER_ID}", "USER_ID",
308 userId);
Vernon Mauery7a3296d2021-08-05 11:08:23 -0700309 return ipmi::responseParmOutOfRange();
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530310 }
Vernon Mauery7a3296d2021-08-05 11:08:23 -0700311
Vernon Mauery7a3296d2021-08-05 11:08:23 -0700312 if (operation == opSetPassword)
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530313 {
Vernon Mauery7a3296d2021-08-05 11:08:23 -0700314 // turn the non-nul terminated SecureBuffer into a SecureString
315 SecureString password(
316 reinterpret_cast<const char*>(userPassword.data()), passwordLength);
317 ipmi::Cc res = ipmiUserSetUserPassword(userId, password.data());
318 return ipmi::response(res);
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530319 }
Vernon Mauery7a3296d2021-08-05 11:08:23 -0700320 else if (operation == opEnableUser || operation == opDisableUser)
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530321 {
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -0500322 ipmi::Cc res = ipmiUserUpdateEnabledState(userId,
323 static_cast<bool>(operation));
Vernon Mauery7a3296d2021-08-05 11:08:23 -0700324 return ipmi::response(res);
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530325 }
Vernon Mauery7a3296d2021-08-05 11:08:23 -0700326 else if (operation == opTestPassword)
Richard Marian Thomaiyar282e79b2018-11-13 19:00:58 +0530327 {
Vernon Mauery1e22a0f2021-07-30 13:36:54 -0700328 SecureString password = ipmiUserGetPassword(userName);
Vernon Mauery7a3296d2021-08-05 11:08:23 -0700329 // extend with zeros, if needed
330 if (password.size() < passwordLength)
331 {
332 password.resize(passwordLength, '\0');
333 }
Vernon Mauery1e22a0f2021-07-30 13:36:54 -0700334 SecureString testPassword(
Vernon Mauery7a3296d2021-08-05 11:08:23 -0700335 reinterpret_cast<const char*>(userPassword.data()), passwordLength);
Vernon Mauery1e22a0f2021-07-30 13:36:54 -0700336 // constant time string compare: always compare exactly as many bytes
337 // as the length of the input, resizing the actual password to match,
338 // maintaining a knowledge if the sizes differed originally
339 static const std::array<char, maxIpmi20PasswordSize> empty = {'\0'};
340 size_t cmpLen = testPassword.size();
341 bool pwLenDiffers = password.size() != cmpLen;
342 const char* cmpPassword = nullptr;
343 if (pwLenDiffers)
344 {
345 cmpPassword = empty.data();
346 }
347 else
348 {
349 cmpPassword = password.data();
350 }
351 bool pwBad = CRYPTO_memcmp(cmpPassword, testPassword.data(), cmpLen);
352 pwBad |= pwLenDiffers;
353 if (pwBad)
Richard Marian Thomaiyar282e79b2018-11-13 19:00:58 +0530354 {
George Liu82844ef2024-07-17 17:03:56 +0800355 lg2::debug("Test password failed, user Id: {USER_ID}", "USER_ID",
356 userId);
Vernon Mauery7a3296d2021-08-05 11:08:23 -0700357 static constexpr ipmi::Cc ipmiCCPasswdFailMismatch = 0x80;
358 return ipmi::response(ipmiCCPasswdFailMismatch);
Richard Marian Thomaiyar282e79b2018-11-13 19:00:58 +0530359 }
Vernon Mauery7a3296d2021-08-05 11:08:23 -0700360 return ipmi::responseSuccess();
Richard Marian Thomaiyar282e79b2018-11-13 19:00:58 +0530361 }
Vernon Mauery7a3296d2021-08-05 11:08:23 -0700362 return ipmi::responseInvalidFieldRequest();
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530363}
364
smritic46f6cd2019-03-20 14:09:41 +0530365/** @brief implements the get channel authentication command
366 * @param ctx - IPMI context pointer (for channel)
367 * @param extData - get IPMI 2.0 extended data
368 * @param reserved1 - skip 3 bits
369 * @param chNum - channel number to get info about
370 * @param reserved2 - skip 4 bits
371 * @param privLevel - requested privilege level
372
373 * @returns ipmi completion code plus response data
374 * - channel number
375 * - rmcpAuthTypes - RMCP auth types (IPMI 1.5)
376 * - reserved1
377 * - extDataSupport - true for IPMI 2.0 extensions
378 * - anonymousLogin - true for anonymous login enabled
379 * - nullUsers - true for null user names enabled
380 * - nonNullUsers - true for non-null usernames enabled
381 * - userAuth - false for user authentication enabled
382 * - perMessageAuth - false for per message authentication enabled
383 * - KGStatus - true for Kg required for authentication
384 * - reserved2
385 * - rmcp - RMCP (IPMI 1.5) connection support
386 * - rmcpp - RMCP+ (IPMI 2.0) connection support
387 * - reserved3
388 * - oemID - OEM IANA of any OEM auth support
389 * - oemAuxillary - OEM data for auth
390 */
391ipmi::RspType<uint8_t, // channel number
392 uint6_t, // rmcpAuthTypes
393 bool, // reserved1
394 bool, // extDataSupport
395 bool, // anonymousLogin
396 bool, // nullUsers
397 bool, // nonNullUsers
398 bool, // userAuth
399 bool, // perMessageAuth
400 bool, // KGStatus
401 uint2_t, // reserved2
402 bool, // rmcp
403 bool, // rmcpp
404 uint6_t, // reserved3
405 uint24_t, // oemID
406 uint8_t // oemAuxillary
407 >
408 ipmiGetChannelAuthenticationCapabilities(ipmi::Context::ptr ctx,
409 uint4_t chNum, uint3_t reserved1,
Willy Tu11d68892022-01-20 10:37:34 -0800410 [[maybe_unused]] bool extData,
411 uint4_t privLevel,
smritic46f6cd2019-03-20 14:09:41 +0530412 uint4_t reserved2)
413{
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -0500414 uint8_t channel = convertCurrentChannelNum(static_cast<uint8_t>(chNum),
415 ctx->channel);
smritic46f6cd2019-03-20 14:09:41 +0530416
417 if (reserved1 || reserved2 || !isValidChannel(channel) ||
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +0000418 !isValidPrivLimit(static_cast<uint8_t>(privLevel)))
smritic46f6cd2019-03-20 14:09:41 +0530419 {
George Liu82844ef2024-07-17 17:03:56 +0800420 lg2::debug("Get channel auth capabilities - Invalid field in request");
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +0000421 return ipmi::responseInvalidFieldRequest();
422 }
423
424 if (getChannelSessionSupport(channel) == EChannelSessSupported::none)
425 {
George Liu82844ef2024-07-17 17:03:56 +0800426 lg2::debug("Get channel auth capabilities - No support on channel");
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +0000427 return ipmi::response(ccActionNotSupportedForChannel);
smritic46f6cd2019-03-20 14:09:41 +0530428 }
429
430 constexpr bool extDataSupport = true; // true for IPMI 2.0 extensions
431 constexpr bool reserved3 = false;
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -0500432 constexpr uint6_t rmcpAuthTypes = 0; // IPMI 1.5 auth types - not supported
smritic46f6cd2019-03-20 14:09:41 +0530433 constexpr uint2_t reserved4 = 0;
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -0500434 constexpr bool KGStatus = false; // Not supporting now.
smritic46f6cd2019-03-20 14:09:41 +0530435 constexpr bool perMessageAuth = false; // Per message auth - enabled
436 constexpr bool userAuth = false; // User authentication - enabled
437 constexpr bool nullUsers = false; // Null user names - not supported
438 constexpr bool anonymousLogin = false; // Anonymous login - not supported
439 constexpr uint6_t reserved5 = 0;
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -0500440 constexpr bool rmcpp = true; // IPMI 2.0 - supported
441 constexpr bool rmcp = false; // IPMI 1.5 - not supported
smritic46f6cd2019-03-20 14:09:41 +0530442 constexpr uint24_t oemID = 0;
443 constexpr uint8_t oemAuxillary = 0;
444
445 bool nonNullUsers = 0;
446 uint8_t maxChUsers = 0, enabledUsers = 0, fixedUsers = 0;
447 ipmi::ipmiUserGetAllCounts(maxChUsers, enabledUsers, fixedUsers);
448 nonNullUsers = enabledUsers > 0;
449
450 return ipmi::responseSuccess(
451 channel, rmcpAuthTypes, reserved3, extDataSupport, anonymousLogin,
452 nullUsers, nonNullUsers, userAuth, perMessageAuth, KGStatus, reserved4,
453 rmcp, rmcpp, reserved5, oemID, oemAuxillary);
454}
455
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000456/** @brief implements the set user payload access command.
457 * @param ctx - IPMI context pointer (for channel)
458 * @param channel - channel number (4 bits)
459 * @param reserved1 - skip 4 bits
460 * @param userId - user id (6 bits)
461 * @param operation - access ENABLE /DISABLE. (2 bits)
462 * @param stdPayload0 - IPMI - reserved. (1 bit)
463 * @param stdPayload1 - SOL. (1 bit)
464 * @param stdPayload2 - (1 bit)
465 * @param stdPayload3 - (1 bit)
466 * @param stdPayload4 - (1 bit)
467 * @param stdPayload5 - (1 bit)
468 * @param stdPayload6 - (1 bit)
469 * @param stdPayload7 - (1 bit)
470 * @param stdPayloadEnables2Reserved - (8 bits)
471 * @param oemPayload0 - (1 bit)
472 * @param oemPayload1 - (1 bit)
473 * @param oemPayload2 - (1 bit)
474 * @param oemPayload3 - (1 bit)
475 * @param oemPayload4 - (1 bit)
476 * @param oemPayload5 - (1 bit)
477 * @param oemPayload6 - (1 bit)
478 * @param oemPayload7 - (1 bit)
479 * @param oemPayloadEnables2Reserved - (8 bits)
480 *
481 * @returns IPMI completion code
482 */
483ipmi::RspType<> ipmiSetUserPayloadAccess(
484 ipmi::Context::ptr ctx,
485
486 uint4_t channel, uint4_t reserved,
487
488 uint6_t userId, uint2_t operation,
489
490 bool stdPayload0ipmiReserved, bool stdPayload1SOL, bool stdPayload2,
491 bool stdPayload3, bool stdPayload4, bool stdPayload5, bool stdPayload6,
492 bool stdPayload7,
493
494 uint8_t stdPayloadEnables2Reserved,
495
496 bool oemPayload0, bool oemPayload1, bool oemPayload2, bool oemPayload3,
497 bool oemPayload4, bool oemPayload5, bool oemPayload6, bool oemPayload7,
498
499 uint8_t oemPayloadEnables2Reserved)
500{
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -0500501 auto chNum = convertCurrentChannelNum(static_cast<uint8_t>(channel),
502 ctx->channel);
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000503 // Validate the reserved args. Only SOL payload is supported as on date.
504 if (reserved || stdPayload0ipmiReserved || stdPayload2 || stdPayload3 ||
505 stdPayload4 || stdPayload5 || stdPayload6 || stdPayload7 ||
506 oemPayload0 || oemPayload1 || oemPayload2 || oemPayload3 ||
507 oemPayload4 || oemPayload5 || oemPayload6 || oemPayload7 ||
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +0000508 stdPayloadEnables2Reserved || oemPayloadEnables2Reserved ||
509 !isValidChannel(chNum))
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000510 {
511 return ipmi::responseInvalidFieldRequest();
512 }
513
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +0000514 if ((operation != enableOperation && operation != disableOperation))
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000515 {
516 return ipmi::responseInvalidFieldRequest();
517 }
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +0000518 if (getChannelSessionSupport(chNum) == EChannelSessSupported::none)
519 {
520 return ipmi::response(ccActionNotSupportedForChannel);
521 }
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000522 if (!ipmiUserIsValidUserId(static_cast<uint8_t>(userId)))
523 {
524 return ipmi::responseParmOutOfRange();
525 }
526
Willy Tu11d68892022-01-20 10:37:34 -0800527 PayloadAccess payloadAccess = {};
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000528 payloadAccess.stdPayloadEnables1[1] = stdPayload1SOL;
529
530 return ipmi::response(ipmiUserSetUserPayloadAccess(
531 chNum, static_cast<uint8_t>(operation), static_cast<uint8_t>(userId),
532 payloadAccess));
533}
534
535/** @brief implements the get user payload access command
536 * This command returns information about user payload enable settings
537 * that were set using the 'Set User Payload Access' Command.
538 *
539 * @param ctx - IPMI context pointer (for channel)
540 * @param channel - channel number
541 * @param reserved1 - skip 4 bits
542 * @param userId - user id
543 * @param reserved2 - skip 2 bits
544 *
545 * @returns IPMI completion code plus response data
546 * - stdPayload0ipmiReserved - IPMI payload (reserved).
547 * - stdPayload1SOL - SOL payload
548 * - stdPayload2
549 * - stdPayload3
550 * - stdPayload4
551 * - stdPayload5
552 * - stdPayload6
553 * - stdPayload7
554
555 * - stdPayloadEnables2Reserved - Reserved.
556
557 * - oemPayload0
558 * - oemPayload1
559 * - oemPayload2
560 * - oemPayload3
561 * - oemPayload4
562 * - oemPayload5
563 * - oemPayload6
564 * - oemPayload7
565
566 * - oemPayloadEnables2Reserved - Reserved
567 */
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -0500568ipmi::RspType<bool, // stdPayload0ipmiReserved
569 bool, // stdPayload1SOL
570 bool, // stdPayload2
571 bool, // stdPayload3
572 bool, // stdPayload4
573 bool, // stdPayload5
574 bool, // stdPayload6
575 bool, // stdPayload7
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000576
577 uint8_t, // stdPayloadEnables2Reserved
578
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -0500579 bool, // oemPayload0
580 bool, // oemPayload1
581 bool, // oemPayload2
582 bool, // oemPayload3
583 bool, // oemPayload4
584 bool, // oemPayload5
585 bool, // oemPayload6
586 bool, // oemPayload7
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000587
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -0500588 uint8_t // oemPayloadEnables2Reserved
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000589 >
590 ipmiGetUserPayloadAccess(ipmi::Context::ptr ctx,
591
592 uint4_t channel, uint4_t reserved1,
593
594 uint6_t userId, uint2_t reserved2)
595{
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -0500596 uint8_t chNum = convertCurrentChannelNum(static_cast<uint8_t>(channel),
597 ctx->channel);
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +0000598
599 if (reserved1 || reserved2 || !isValidChannel(chNum))
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000600 {
601 return ipmi::responseInvalidFieldRequest();
602 }
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +0000603 if (getChannelSessionSupport(chNum) == EChannelSessSupported::none)
604 {
605 return ipmi::response(ccActionNotSupportedForChannel);
606 }
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000607 if (!ipmiUserIsValidUserId(static_cast<uint8_t>(userId)))
608 {
609 return ipmi::responseParmOutOfRange();
610 }
611
612 ipmi::Cc retStatus;
613 PayloadAccess payloadAccess = {};
614 retStatus = ipmiUserGetUserPayloadAccess(
615 chNum, static_cast<uint8_t>(userId), payloadAccess);
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000616 if (retStatus != ccSuccess)
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000617 {
618 return ipmi::response(retStatus);
619 }
620 constexpr uint8_t res8bits = 0;
621 return ipmi::responseSuccess(payloadAccess.stdPayloadEnables1.test(0),
622 payloadAccess.stdPayloadEnables1.test(1),
623 payloadAccess.stdPayloadEnables1.test(2),
624 payloadAccess.stdPayloadEnables1.test(3),
625 payloadAccess.stdPayloadEnables1.test(4),
626 payloadAccess.stdPayloadEnables1.test(5),
627 payloadAccess.stdPayloadEnables1.test(6),
628 payloadAccess.stdPayloadEnables1.test(7),
629
630 res8bits,
631
632 payloadAccess.oemPayloadEnables1.test(0),
633 payloadAccess.oemPayloadEnables1.test(1),
634 payloadAccess.oemPayloadEnables1.test(2),
635 payloadAccess.oemPayloadEnables1.test(3),
636 payloadAccess.oemPayloadEnables1.test(4),
637 payloadAccess.oemPayloadEnables1.test(5),
638 payloadAccess.oemPayloadEnables1.test(6),
639 payloadAccess.oemPayloadEnables1.test(7),
640
641 res8bits);
642}
643
William A. Kennington III343d0612018-12-10 15:56:24 -0800644void registerUserIpmiFunctions() __attribute__((constructor));
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530645void registerUserIpmiFunctions()
646{
Richard Marian Thomaiyar0be80bd2020-01-10 12:20:16 +0530647 post_work([]() { ipmiUserInit(); });
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530648 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
649 ipmi::app::cmdSetUserAccessCommand,
650 ipmi::Privilege::Admin, ipmiSetUserAccess);
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530651
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530652 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
653 ipmi::app::cmdGetUserAccessCommand,
ankita prasadbd604762023-01-18 10:56:43 +0000654 ipmi::Privilege::Admin, ipmiGetUserAccess);
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530655
Vernon Mauery3c89de12021-08-05 11:08:23 -0700656 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
657 ipmi::app::cmdGetUserNameCommand,
ankita prasadbd604762023-01-18 10:56:43 +0000658 ipmi::Privilege::Admin, ipmiGetUserName);
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530659
Vernon Maueryac30b392021-08-05 11:08:23 -0700660 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
661 ipmi::app::cmdSetUserName, ipmi::Privilege::Admin,
662 ipmiSetUserName);
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530663
Vernon Mauery7a3296d2021-08-05 11:08:23 -0700664 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
665 ipmi::app::cmdSetUserPasswordCommand,
666 ipmi::Privilege::Admin, ipmiSetUserPassword);
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530667
smritic46f6cd2019-03-20 14:09:41 +0530668 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
669 ipmi::app::cmdGetChannelAuthCapabilities,
670 ipmi::Privilege::Callback,
671 ipmiGetChannelAuthenticationCapabilities);
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000672
673 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
674 ipmi::app::cmdSetUserPayloadAccess,
675 ipmi::Privilege::Admin, ipmiSetUserPayloadAccess);
676
677 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
678 ipmi::app::cmdGetUserPayloadAccess,
679 ipmi::Privilege::Operator, ipmiGetUserPayloadAccess);
680
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530681 return;
682}
683} // namespace ipmi