blob: 3e1b3caef959f9a4d4eed2114f94709adc5d30e3 [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
Richard Marian Thomaiyar06df8762018-12-08 17:38:25 +053019#include "channel_layer.hpp"
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +053020#include "user_layer.hpp"
21
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +053022#include <security/pam_appl.h>
23
Vernon Mauerye08fbff2019-04-03 09:19:34 -070024#include <ipmid/api.hpp>
George Liu82844ef2024-07-17 17:03:56 +080025#include <phosphor-logging/lg2.hpp>
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -050026
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +053027#include <regex>
28
29namespace ipmi
30{
31
Saravanan Palanisamy77381f12019-05-15 22:33:17 +000032static constexpr uint8_t enableOperation = 0x00;
33static constexpr uint8_t disableOperation = 0x01;
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +053034
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +053035/** @brief implements the set user access command
36 * @param ctx - IPMI context pointer (for channel)
37 * @param channel - channel number
38 * @param ipmiEnabled - indicates ipmi messaging state
39 * @param linkAuthEnabled - indicates link authentication state
40 * @param accessCallback - indicates callback state
41 * @param bitsUpdate - indicates update request
42 * @param userId - user id
43 * @param reserved1 - skip 2 bits
44 * @param privilege - user privilege
45 * @param reserved2 - skip 4 bits
46 * @param sessionLimit - optional - unused for now
47 *
48 * @returns ipmi completion code
49 */
Patrick Williams1318a5e2024-08-16 15:19:54 -040050ipmi::RspType<> ipmiSetUserAccess(
51 ipmi::Context::ptr ctx, uint4_t channel, uint1_t ipmiEnabled,
52 uint1_t linkAuthEnabled, uint1_t accessCallback, uint1_t bitsUpdate,
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +053053
Patrick Williams1318a5e2024-08-16 15:19:54 -040054 uint6_t userId, uint2_t reserved1,
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +053055
Patrick Williams1318a5e2024-08-16 15:19:54 -040056 uint4_t privilege, uint4_t reserved2,
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +053057
Patrick Williams1318a5e2024-08-16 15:19:54 -040058 std::optional<uint8_t> sessionLimit)
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +053059{
60 uint8_t sessLimit = sessionLimit.value_or(0);
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +000061 if (reserved1 || reserved2 || sessLimit ||
62 !ipmiUserIsValidPrivilege(static_cast<uint8_t>(privilege)))
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +053063 {
George Liu82844ef2024-07-17 17:03:56 +080064 lg2::debug("Set user access - Invalid field in request");
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +053065 return ipmi::responseInvalidFieldRequest();
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +053066 }
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +000067
Patrick Williams1318a5e2024-08-16 15:19:54 -040068 uint8_t chNum =
69 convertCurrentChannelNum(static_cast<uint8_t>(channel), ctx->channel);
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +000070 if (!isValidChannel(chNum))
71 {
George Liu82844ef2024-07-17 17:03:56 +080072 lg2::debug("Set user access - Invalid channel request");
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +000073 return ipmi::response(invalidChannel);
74 }
75 if (getChannelSessionSupport(chNum) == EChannelSessSupported::none)
76 {
George Liu82844ef2024-07-17 17:03:56 +080077 lg2::debug("Set user access - No support on channel");
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +000078 return ipmi::response(ccActionNotSupportedForChannel);
79 }
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +053080 if (!ipmiUserIsValidUserId(static_cast<uint8_t>(userId)))
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +053081 {
George Liu82844ef2024-07-17 17:03:56 +080082 lg2::debug("Set user access - Parameter out of range");
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +053083 return ipmi::responseParmOutOfRange();
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +053084 }
Richard Marian Thomaiyar06df8762018-12-08 17:38:25 +053085
Willy Tu11d68892022-01-20 10:37:34 -080086 PrivAccess privAccess = {};
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +053087 if (bitsUpdate)
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +053088 {
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +053089 privAccess.ipmiEnabled = static_cast<uint8_t>(ipmiEnabled);
90 privAccess.linkAuthEnabled = static_cast<uint8_t>(linkAuthEnabled);
91 privAccess.accessCallback = static_cast<uint8_t>(accessCallback);
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +053092 }
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +053093 privAccess.privilege = static_cast<uint8_t>(privilege);
94 return ipmi::response(
95 ipmiUserSetPrivilegeAccess(static_cast<uint8_t>(userId), chNum,
96 privAccess, static_cast<bool>(bitsUpdate)));
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +053097}
98
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +053099/** @brief implements the set user access command
100 * @param ctx - IPMI context pointer (for channel)
101 * @param channel - channel number
102 * @param reserved1 - skip 4 bits
103 * @param userId - user id
104 * @param reserved2 - skip 2 bits
105 *
106 * @returns ipmi completion code plus response data
107 * - maxChUsers - max channel users
108 * - reserved1 - skip 2 bits
109 * - enabledUsers - enabled users count
110 * - enabledStatus - enabled status
111 * - fixedUsers - fixed users count
112 * - reserved2 - skip 2 bits
113 * - privilege - user privilege
114 * - ipmiEnabled - ipmi messaging state
115 * - linkAuthEnabled - link authenticatin state
116 * - accessCallback - callback state
117 * - reserved - skip 1 bit
118 */
119ipmi::RspType<uint6_t, // max channel users
120 uint2_t, // reserved1
121
122 uint6_t, // enabled users count
123 uint2_t, // enabled status
124
125 uint6_t, // fixed users count
126 uint2_t, // reserved2
127
128 uint4_t, // privilege
129 uint1_t, // ipmi messaging state
130 uint1_t, // link authentication state
131 uint1_t, // access callback state
132 uint1_t // reserved3
133 >
134 ipmiGetUserAccess(ipmi::Context::ptr ctx, uint4_t channel,
135 uint4_t reserved1,
136
137 uint6_t userId, uint2_t reserved2)
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530138{
Patrick Williams1318a5e2024-08-16 15:19:54 -0400139 uint8_t chNum =
140 convertCurrentChannelNum(static_cast<uint8_t>(channel), ctx->channel);
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +0000141
142 if (reserved1 || reserved2 || !isValidChannel(chNum))
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530143 {
George Liu82844ef2024-07-17 17:03:56 +0800144 lg2::debug("Get user access - Invalid field in request");
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530145 return ipmi::responseInvalidFieldRequest();
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530146 }
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +0000147
148 if (getChannelSessionSupport(chNum) == EChannelSessSupported::none)
149 {
George Liu82844ef2024-07-17 17:03:56 +0800150 lg2::debug("Get user access - No support on channel");
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +0000151 return ipmi::response(ccActionNotSupportedForChannel);
152 }
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530153 if (!ipmiUserIsValidUserId(static_cast<uint8_t>(userId)))
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530154 {
George Liu82844ef2024-07-17 17:03:56 +0800155 lg2::debug("Get user access - Parameter out of range");
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530156 return ipmi::responseParmOutOfRange();
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530157 }
158
159 uint8_t maxChUsers = 0, enabledUsers = 0, fixedUsers = 0;
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530160 ipmi::Cc retStatus;
Richard Marian Thomaiyarb6771e02019-01-29 14:42:44 +0530161 retStatus = ipmiUserGetAllCounts(maxChUsers, enabledUsers, fixedUsers);
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000162 if (retStatus != ccSuccess)
Richard Marian Thomaiyarb6771e02019-01-29 14:42:44 +0530163 {
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530164 return ipmi::response(retStatus);
Richard Marian Thomaiyarb6771e02019-01-29 14:42:44 +0530165 }
166
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530167 bool enabledState = false;
Patrick Williams1318a5e2024-08-16 15:19:54 -0400168 retStatus =
169 ipmiUserCheckEnabled(static_cast<uint8_t>(userId), enabledState);
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000170 if (retStatus != ccSuccess)
Richard Marian Thomaiyarb6771e02019-01-29 14:42:44 +0530171 {
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530172 return ipmi::response(retStatus);
Richard Marian Thomaiyarb6771e02019-01-29 14:42:44 +0530173 }
174
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530175 uint2_t enabledStatus = enabledState ? userIdEnabledViaSetPassword
176 : userIdDisabledViaSetPassword;
177 PrivAccess privAccess{};
178 retStatus = ipmiUserGetPrivilegeAccess(static_cast<uint8_t>(userId), chNum,
179 privAccess);
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000180 if (retStatus != ccSuccess)
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530181 {
182 return ipmi::response(retStatus);
183 }
184 constexpr uint2_t res2Bits = 0;
185 return ipmi::responseSuccess(
186 static_cast<uint6_t>(maxChUsers), res2Bits,
187
188 static_cast<uint6_t>(enabledUsers), enabledStatus,
189
190 static_cast<uint6_t>(fixedUsers), res2Bits,
191
192 static_cast<uint4_t>(privAccess.privilege),
193 static_cast<uint1_t>(privAccess.ipmiEnabled),
194 static_cast<uint1_t>(privAccess.linkAuthEnabled),
195 static_cast<uint1_t>(privAccess.accessCallback),
196 static_cast<uint1_t>(privAccess.reserved));
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530197}
198
Vernon Maueryac30b392021-08-05 11:08:23 -0700199/** @brief implementes the get user name command
200 * @param[in] ctx - ipmi command context
201 * @param[in] userId - 6-bit user ID
202 * @param[in] reserved - 2-bits reserved
203 * @param[in] name - 16-byte array for username
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530204
Vernon Maueryac30b392021-08-05 11:08:23 -0700205 * @returns ipmi response
206 */
Patrick Williams1318a5e2024-08-16 15:19:54 -0400207ipmi::RspType<> ipmiSetUserName(
208 [[maybe_unused]] ipmi::Context::ptr ctx, uint6_t id, uint2_t reserved,
209 const std::array<uint8_t, ipmi::ipmiMaxUserName>& name)
Vernon Maueryac30b392021-08-05 11:08:23 -0700210{
211 if (reserved)
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530212 {
Vernon Maueryac30b392021-08-05 11:08:23 -0700213 return ipmi::responseInvalidFieldRequest();
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530214 }
Vernon Maueryac30b392021-08-05 11:08:23 -0700215 uint8_t userId = static_cast<uint8_t>(id);
216 if (!ipmiUserIsValidUserId(userId))
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530217 {
George Liu82844ef2024-07-17 17:03:56 +0800218 lg2::debug("Set user name - Invalid user id");
Vernon Maueryac30b392021-08-05 11:08:23 -0700219 return ipmi::responseParmOutOfRange();
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530220 }
221
Vernon Maueryac30b392021-08-05 11:08:23 -0700222 size_t nameLen = strnlen(reinterpret_cast<const char*>(name.data()),
223 ipmi::ipmiMaxUserName);
224 const std::string strUserName(reinterpret_cast<const char*>(name.data()),
jayaprakash Mutyalacdcdf2b2020-03-28 00:12:05 +0000225 nameLen);
226
Vernon Maueryac30b392021-08-05 11:08:23 -0700227 ipmi::Cc res = ipmiUserSetUserName(userId, strUserName);
228 return ipmi::response(res);
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530229}
230
231/** @brief implementes the get user name command
Vernon Mauery3c89de12021-08-05 11:08:23 -0700232 * @param[in] ctx - ipmi command context
233 * @param[in] userId - 6-bit user ID
234 * @param[in] reserved - 2-bits reserved
235
236 * @returns ipmi response with 16-byte username
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530237 */
Vernon Mauery3c89de12021-08-05 11:08:23 -0700238ipmi::RspType<std::array<uint8_t, ipmi::ipmiMaxUserName>> // user name
Willy Tu11d68892022-01-20 10:37:34 -0800239 ipmiGetUserName([[maybe_unused]] ipmi::Context::ptr ctx, uint6_t id,
240 uint2_t reserved)
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530241{
Vernon Mauery3c89de12021-08-05 11:08:23 -0700242 if (reserved)
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530243 {
Vernon Mauery3c89de12021-08-05 11:08:23 -0700244 return ipmi::responseInvalidFieldRequest();
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530245 }
246
Vernon Mauery3c89de12021-08-05 11:08:23 -0700247 uint8_t userId = static_cast<uint8_t>(id);
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530248 std::string userName;
Vernon Mauery3c89de12021-08-05 11:08:23 -0700249 if (ipmiUserGetUserName(userId, userName) != ccSuccess)
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530250 { // Invalid User ID
George Liu82844ef2024-07-17 17:03:56 +0800251 lg2::debug("User Name not found, user Id: {USER_ID}", "USER_ID",
252 userId);
Vernon Mauery3c89de12021-08-05 11:08:23 -0700253 return ipmi::responseParmOutOfRange();
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530254 }
Vernon Mauery3c89de12021-08-05 11:08:23 -0700255 // copy the std::string into a fixed array
256 if (userName.size() > ipmi::ipmiMaxUserName)
257 {
258 return ipmi::responseUnspecifiedError();
259 }
260 std::array<uint8_t, ipmi::ipmiMaxUserName> userNameFixed;
261 std::fill(userNameFixed.begin(), userNameFixed.end(), 0);
262 std::copy(userName.begin(), userName.end(), userNameFixed.begin());
263 return ipmi::responseSuccess(std::move(userNameFixed));
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530264}
265
Vernon Mauery7a3296d2021-08-05 11:08:23 -0700266/** @brief implementes the get user name command
267 * @param[in] ctx - ipmi command context
268 * @param[in] userId - 6-bit user ID
269 * @param[in] reserved - 2-bits reserved
270
271 * @returns ipmi response with 16-byte username
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530272 */
Vernon Mauery7a3296d2021-08-05 11:08:23 -0700273ipmi::RspType<> // user name
Willy Tu11d68892022-01-20 10:37:34 -0800274 ipmiSetUserPassword([[maybe_unused]] ipmi::Context::ptr ctx, uint6_t id,
275 bool reserved1, bool pwLen20, uint2_t operation,
276 uint6_t reserved2, SecureBuffer& userPassword)
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530277{
Vernon Mauery7a3296d2021-08-05 11:08:23 -0700278 if (reserved1 || reserved2)
Snehalatha Venkatesh37b1d1a2021-06-28 10:13:37 +0000279 {
George Liu82844ef2024-07-17 17:03:56 +0800280 lg2::debug("Invalid data field in request");
Vernon Mauery7a3296d2021-08-05 11:08:23 -0700281 return ipmi::responseInvalidFieldRequest();
Snehalatha Venkatesh37b1d1a2021-06-28 10:13:37 +0000282 }
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530283
Ayushi Smriti29b9f312021-09-24 12:29:23 +0530284 static constexpr uint2_t opDisableUser = 0x00;
285 static constexpr uint2_t opEnableUser = 0x01;
286 static constexpr uint2_t opSetPassword = 0x02;
287 static constexpr uint2_t opTestPassword = 0x03;
288
289 // If set / test password operation then password size has to be 16 or 20
290 // bytes based on the password size bit
291 if (((operation == opSetPassword) || (operation == opTestPassword)) &&
292 ((pwLen20 && (userPassword.size() != maxIpmi20PasswordSize)) ||
293 (!pwLen20 && (userPassword.size() != maxIpmi15PasswordSize))))
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530294 {
George Liu82844ef2024-07-17 17:03:56 +0800295 lg2::debug("Invalid Length");
Vernon Mauery7a3296d2021-08-05 11:08:23 -0700296 return ipmi::responseReqDataLenInvalid();
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530297 }
Ayushi Smriti29b9f312021-09-24 12:29:23 +0530298
Vernon Mauery7a3296d2021-08-05 11:08:23 -0700299 size_t passwordLength = userPassword.size();
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530300
Vernon Mauery7a3296d2021-08-05 11:08:23 -0700301 uint8_t userId = static_cast<uint8_t>(id);
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530302 std::string userName;
Vernon Mauery7a3296d2021-08-05 11:08:23 -0700303 if (ipmiUserGetUserName(userId, userName) != ccSuccess)
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530304 {
George Liu82844ef2024-07-17 17:03:56 +0800305 lg2::debug("User Name not found, user Id: {USER_ID}", "USER_ID",
306 userId);
Vernon Mauery7a3296d2021-08-05 11:08:23 -0700307 return ipmi::responseParmOutOfRange();
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530308 }
Vernon Mauery7a3296d2021-08-05 11:08:23 -0700309
Vernon Mauery7a3296d2021-08-05 11:08:23 -0700310 if (operation == opSetPassword)
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530311 {
Vernon Mauery7a3296d2021-08-05 11:08:23 -0700312 // turn the non-nul terminated SecureBuffer into a SecureString
313 SecureString password(
314 reinterpret_cast<const char*>(userPassword.data()), passwordLength);
315 ipmi::Cc res = ipmiUserSetUserPassword(userId, password.data());
316 return ipmi::response(res);
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530317 }
Vernon Mauery7a3296d2021-08-05 11:08:23 -0700318 else if (operation == opEnableUser || operation == opDisableUser)
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530319 {
Patrick Williams1318a5e2024-08-16 15:19:54 -0400320 ipmi::Cc res =
321 ipmiUserUpdateEnabledState(userId, static_cast<bool>(operation));
Vernon Mauery7a3296d2021-08-05 11:08:23 -0700322 return ipmi::response(res);
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530323 }
Vernon Mauery7a3296d2021-08-05 11:08:23 -0700324 else if (operation == opTestPassword)
Richard Marian Thomaiyar282e79b2018-11-13 19:00:58 +0530325 {
Vernon Mauery1e22a0f2021-07-30 13:36:54 -0700326 SecureString password = ipmiUserGetPassword(userName);
Vernon Mauery7a3296d2021-08-05 11:08:23 -0700327 // extend with zeros, if needed
328 if (password.size() < passwordLength)
329 {
330 password.resize(passwordLength, '\0');
331 }
Vernon Mauery1e22a0f2021-07-30 13:36:54 -0700332 SecureString testPassword(
Vernon Mauery7a3296d2021-08-05 11:08:23 -0700333 reinterpret_cast<const char*>(userPassword.data()), passwordLength);
Vernon Mauery1e22a0f2021-07-30 13:36:54 -0700334 // constant time string compare: always compare exactly as many bytes
335 // as the length of the input, resizing the actual password to match,
336 // maintaining a knowledge if the sizes differed originally
337 static const std::array<char, maxIpmi20PasswordSize> empty = {'\0'};
338 size_t cmpLen = testPassword.size();
339 bool pwLenDiffers = password.size() != cmpLen;
340 const char* cmpPassword = nullptr;
341 if (pwLenDiffers)
342 {
343 cmpPassword = empty.data();
344 }
345 else
346 {
347 cmpPassword = password.data();
348 }
349 bool pwBad = CRYPTO_memcmp(cmpPassword, testPassword.data(), cmpLen);
350 pwBad |= pwLenDiffers;
351 if (pwBad)
Richard Marian Thomaiyar282e79b2018-11-13 19:00:58 +0530352 {
George Liu82844ef2024-07-17 17:03:56 +0800353 lg2::debug("Test password failed, user Id: {USER_ID}", "USER_ID",
354 userId);
Vernon Mauery7a3296d2021-08-05 11:08:23 -0700355 return ipmi::response(ipmiCCPasswdFailMismatch);
Richard Marian Thomaiyar282e79b2018-11-13 19:00:58 +0530356 }
Vernon Mauery7a3296d2021-08-05 11:08:23 -0700357 return ipmi::responseSuccess();
Richard Marian Thomaiyar282e79b2018-11-13 19:00:58 +0530358 }
Vernon Mauery7a3296d2021-08-05 11:08:23 -0700359 return ipmi::responseInvalidFieldRequest();
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530360}
361
smritic46f6cd2019-03-20 14:09:41 +0530362/** @brief implements the get channel authentication command
363 * @param ctx - IPMI context pointer (for channel)
364 * @param extData - get IPMI 2.0 extended data
365 * @param reserved1 - skip 3 bits
366 * @param chNum - channel number to get info about
367 * @param reserved2 - skip 4 bits
368 * @param privLevel - requested privilege level
369
370 * @returns ipmi completion code plus response data
371 * - channel number
372 * - rmcpAuthTypes - RMCP auth types (IPMI 1.5)
373 * - reserved1
374 * - extDataSupport - true for IPMI 2.0 extensions
375 * - anonymousLogin - true for anonymous login enabled
376 * - nullUsers - true for null user names enabled
377 * - nonNullUsers - true for non-null usernames enabled
378 * - userAuth - false for user authentication enabled
379 * - perMessageAuth - false for per message authentication enabled
380 * - KGStatus - true for Kg required for authentication
381 * - reserved2
382 * - rmcp - RMCP (IPMI 1.5) connection support
383 * - rmcpp - RMCP+ (IPMI 2.0) connection support
384 * - reserved3
385 * - oemID - OEM IANA of any OEM auth support
386 * - oemAuxillary - OEM data for auth
387 */
388ipmi::RspType<uint8_t, // channel number
389 uint6_t, // rmcpAuthTypes
390 bool, // reserved1
391 bool, // extDataSupport
392 bool, // anonymousLogin
393 bool, // nullUsers
394 bool, // nonNullUsers
395 bool, // userAuth
396 bool, // perMessageAuth
397 bool, // KGStatus
398 uint2_t, // reserved2
399 bool, // rmcp
400 bool, // rmcpp
401 uint6_t, // reserved3
402 uint24_t, // oemID
403 uint8_t // oemAuxillary
404 >
Patrick Williams1318a5e2024-08-16 15:19:54 -0400405 ipmiGetChannelAuthenticationCapabilities(
406 ipmi::Context::ptr ctx, uint4_t chNum, uint3_t reserved1,
407 [[maybe_unused]] bool extData, uint4_t privLevel, uint4_t reserved2)
smritic46f6cd2019-03-20 14:09:41 +0530408{
Patrick Williams1318a5e2024-08-16 15:19:54 -0400409 uint8_t channel =
410 convertCurrentChannelNum(static_cast<uint8_t>(chNum), ctx->channel);
smritic46f6cd2019-03-20 14:09:41 +0530411
412 if (reserved1 || reserved2 || !isValidChannel(channel) ||
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +0000413 !isValidPrivLimit(static_cast<uint8_t>(privLevel)))
smritic46f6cd2019-03-20 14:09:41 +0530414 {
George Liu82844ef2024-07-17 17:03:56 +0800415 lg2::debug("Get channel auth capabilities - Invalid field in request");
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +0000416 return ipmi::responseInvalidFieldRequest();
417 }
418
419 if (getChannelSessionSupport(channel) == EChannelSessSupported::none)
420 {
George Liu82844ef2024-07-17 17:03:56 +0800421 lg2::debug("Get channel auth capabilities - No support on channel");
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +0000422 return ipmi::response(ccActionNotSupportedForChannel);
smritic46f6cd2019-03-20 14:09:41 +0530423 }
424
425 constexpr bool extDataSupport = true; // true for IPMI 2.0 extensions
426 constexpr bool reserved3 = false;
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -0500427 constexpr uint6_t rmcpAuthTypes = 0; // IPMI 1.5 auth types - not supported
smritic46f6cd2019-03-20 14:09:41 +0530428 constexpr uint2_t reserved4 = 0;
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -0500429 constexpr bool KGStatus = false; // Not supporting now.
smritic46f6cd2019-03-20 14:09:41 +0530430 constexpr bool perMessageAuth = false; // Per message auth - enabled
431 constexpr bool userAuth = false; // User authentication - enabled
432 constexpr bool nullUsers = false; // Null user names - not supported
433 constexpr bool anonymousLogin = false; // Anonymous login - not supported
434 constexpr uint6_t reserved5 = 0;
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -0500435 constexpr bool rmcpp = true; // IPMI 2.0 - supported
436 constexpr bool rmcp = false; // IPMI 1.5 - not supported
smritic46f6cd2019-03-20 14:09:41 +0530437 constexpr uint24_t oemID = 0;
438 constexpr uint8_t oemAuxillary = 0;
439
440 bool nonNullUsers = 0;
441 uint8_t maxChUsers = 0, enabledUsers = 0, fixedUsers = 0;
442 ipmi::ipmiUserGetAllCounts(maxChUsers, enabledUsers, fixedUsers);
443 nonNullUsers = enabledUsers > 0;
444
445 return ipmi::responseSuccess(
446 channel, rmcpAuthTypes, reserved3, extDataSupport, anonymousLogin,
447 nullUsers, nonNullUsers, userAuth, perMessageAuth, KGStatus, reserved4,
448 rmcp, rmcpp, reserved5, oemID, oemAuxillary);
449}
450
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000451/** @brief implements the set user payload access command.
452 * @param ctx - IPMI context pointer (for channel)
453 * @param channel - channel number (4 bits)
454 * @param reserved1 - skip 4 bits
455 * @param userId - user id (6 bits)
456 * @param operation - access ENABLE /DISABLE. (2 bits)
457 * @param stdPayload0 - IPMI - reserved. (1 bit)
458 * @param stdPayload1 - SOL. (1 bit)
459 * @param stdPayload2 - (1 bit)
460 * @param stdPayload3 - (1 bit)
461 * @param stdPayload4 - (1 bit)
462 * @param stdPayload5 - (1 bit)
463 * @param stdPayload6 - (1 bit)
464 * @param stdPayload7 - (1 bit)
465 * @param stdPayloadEnables2Reserved - (8 bits)
466 * @param oemPayload0 - (1 bit)
467 * @param oemPayload1 - (1 bit)
468 * @param oemPayload2 - (1 bit)
469 * @param oemPayload3 - (1 bit)
470 * @param oemPayload4 - (1 bit)
471 * @param oemPayload5 - (1 bit)
472 * @param oemPayload6 - (1 bit)
473 * @param oemPayload7 - (1 bit)
474 * @param oemPayloadEnables2Reserved - (8 bits)
475 *
476 * @returns IPMI completion code
477 */
478ipmi::RspType<> ipmiSetUserPayloadAccess(
479 ipmi::Context::ptr ctx,
480
481 uint4_t channel, uint4_t reserved,
482
483 uint6_t userId, uint2_t operation,
484
485 bool stdPayload0ipmiReserved, bool stdPayload1SOL, bool stdPayload2,
486 bool stdPayload3, bool stdPayload4, bool stdPayload5, bool stdPayload6,
487 bool stdPayload7,
488
489 uint8_t stdPayloadEnables2Reserved,
490
491 bool oemPayload0, bool oemPayload1, bool oemPayload2, bool oemPayload3,
492 bool oemPayload4, bool oemPayload5, bool oemPayload6, bool oemPayload7,
493
494 uint8_t oemPayloadEnables2Reserved)
495{
Patrick Williams1318a5e2024-08-16 15:19:54 -0400496 auto chNum =
497 convertCurrentChannelNum(static_cast<uint8_t>(channel), ctx->channel);
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000498 // Validate the reserved args. Only SOL payload is supported as on date.
499 if (reserved || stdPayload0ipmiReserved || stdPayload2 || stdPayload3 ||
500 stdPayload4 || stdPayload5 || stdPayload6 || stdPayload7 ||
501 oemPayload0 || oemPayload1 || oemPayload2 || oemPayload3 ||
502 oemPayload4 || oemPayload5 || oemPayload6 || oemPayload7 ||
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +0000503 stdPayloadEnables2Reserved || oemPayloadEnables2Reserved ||
504 !isValidChannel(chNum))
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000505 {
506 return ipmi::responseInvalidFieldRequest();
507 }
508
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +0000509 if ((operation != enableOperation && operation != disableOperation))
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000510 {
511 return ipmi::responseInvalidFieldRequest();
512 }
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +0000513 if (getChannelSessionSupport(chNum) == EChannelSessSupported::none)
514 {
515 return ipmi::response(ccActionNotSupportedForChannel);
516 }
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000517 if (!ipmiUserIsValidUserId(static_cast<uint8_t>(userId)))
518 {
519 return ipmi::responseParmOutOfRange();
520 }
521
Willy Tu11d68892022-01-20 10:37:34 -0800522 PayloadAccess payloadAccess = {};
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000523 payloadAccess.stdPayloadEnables1[1] = stdPayload1SOL;
524
525 return ipmi::response(ipmiUserSetUserPayloadAccess(
526 chNum, static_cast<uint8_t>(operation), static_cast<uint8_t>(userId),
527 payloadAccess));
528}
529
530/** @brief implements the get user payload access command
531 * This command returns information about user payload enable settings
532 * that were set using the 'Set User Payload Access' Command.
533 *
534 * @param ctx - IPMI context pointer (for channel)
535 * @param channel - channel number
536 * @param reserved1 - skip 4 bits
537 * @param userId - user id
538 * @param reserved2 - skip 2 bits
539 *
540 * @returns IPMI completion code plus response data
541 * - stdPayload0ipmiReserved - IPMI payload (reserved).
542 * - stdPayload1SOL - SOL payload
543 * - stdPayload2
544 * - stdPayload3
545 * - stdPayload4
546 * - stdPayload5
547 * - stdPayload6
548 * - stdPayload7
549
550 * - stdPayloadEnables2Reserved - Reserved.
551
552 * - oemPayload0
553 * - oemPayload1
554 * - oemPayload2
555 * - oemPayload3
556 * - oemPayload4
557 * - oemPayload5
558 * - oemPayload6
559 * - oemPayload7
560
561 * - oemPayloadEnables2Reserved - Reserved
562 */
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -0500563ipmi::RspType<bool, // stdPayload0ipmiReserved
564 bool, // stdPayload1SOL
565 bool, // stdPayload2
566 bool, // stdPayload3
567 bool, // stdPayload4
568 bool, // stdPayload5
569 bool, // stdPayload6
570 bool, // stdPayload7
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000571
572 uint8_t, // stdPayloadEnables2Reserved
573
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -0500574 bool, // oemPayload0
575 bool, // oemPayload1
576 bool, // oemPayload2
577 bool, // oemPayload3
578 bool, // oemPayload4
579 bool, // oemPayload5
580 bool, // oemPayload6
581 bool, // oemPayload7
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000582
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -0500583 uint8_t // oemPayloadEnables2Reserved
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000584 >
585 ipmiGetUserPayloadAccess(ipmi::Context::ptr ctx,
586
587 uint4_t channel, uint4_t reserved1,
588
589 uint6_t userId, uint2_t reserved2)
590{
Patrick Williams1318a5e2024-08-16 15:19:54 -0400591 uint8_t chNum =
592 convertCurrentChannelNum(static_cast<uint8_t>(channel), ctx->channel);
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +0000593
594 if (reserved1 || reserved2 || !isValidChannel(chNum))
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000595 {
596 return ipmi::responseInvalidFieldRequest();
597 }
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +0000598 if (getChannelSessionSupport(chNum) == EChannelSessSupported::none)
599 {
600 return ipmi::response(ccActionNotSupportedForChannel);
601 }
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000602 if (!ipmiUserIsValidUserId(static_cast<uint8_t>(userId)))
603 {
604 return ipmi::responseParmOutOfRange();
605 }
606
607 ipmi::Cc retStatus;
608 PayloadAccess payloadAccess = {};
609 retStatus = ipmiUserGetUserPayloadAccess(
610 chNum, static_cast<uint8_t>(userId), payloadAccess);
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000611 if (retStatus != ccSuccess)
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000612 {
613 return ipmi::response(retStatus);
614 }
615 constexpr uint8_t res8bits = 0;
Patrick Williams1318a5e2024-08-16 15:19:54 -0400616 return ipmi::responseSuccess(
617 payloadAccess.stdPayloadEnables1.test(0),
618 payloadAccess.stdPayloadEnables1.test(1),
619 payloadAccess.stdPayloadEnables1.test(2),
620 payloadAccess.stdPayloadEnables1.test(3),
621 payloadAccess.stdPayloadEnables1.test(4),
622 payloadAccess.stdPayloadEnables1.test(5),
623 payloadAccess.stdPayloadEnables1.test(6),
624 payloadAccess.stdPayloadEnables1.test(7),
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000625
Patrick Williams1318a5e2024-08-16 15:19:54 -0400626 res8bits,
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000627
Patrick Williams1318a5e2024-08-16 15:19:54 -0400628 payloadAccess.oemPayloadEnables1.test(0),
629 payloadAccess.oemPayloadEnables1.test(1),
630 payloadAccess.oemPayloadEnables1.test(2),
631 payloadAccess.oemPayloadEnables1.test(3),
632 payloadAccess.oemPayloadEnables1.test(4),
633 payloadAccess.oemPayloadEnables1.test(5),
634 payloadAccess.oemPayloadEnables1.test(6),
635 payloadAccess.oemPayloadEnables1.test(7),
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000636
Patrick Williams1318a5e2024-08-16 15:19:54 -0400637 res8bits);
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000638}
639
William A. Kennington III343d0612018-12-10 15:56:24 -0800640void registerUserIpmiFunctions() __attribute__((constructor));
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530641void registerUserIpmiFunctions()
642{
Richard Marian Thomaiyar0be80bd2020-01-10 12:20:16 +0530643 post_work([]() { ipmiUserInit(); });
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530644 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
645 ipmi::app::cmdSetUserAccessCommand,
646 ipmi::Privilege::Admin, ipmiSetUserAccess);
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530647
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530648 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
649 ipmi::app::cmdGetUserAccessCommand,
ankita prasadbd604762023-01-18 10:56:43 +0000650 ipmi::Privilege::Admin, ipmiGetUserAccess);
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530651
Vernon Mauery3c89de12021-08-05 11:08:23 -0700652 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
653 ipmi::app::cmdGetUserNameCommand,
ankita prasadbd604762023-01-18 10:56:43 +0000654 ipmi::Privilege::Admin, ipmiGetUserName);
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530655
Vernon Maueryac30b392021-08-05 11:08:23 -0700656 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
657 ipmi::app::cmdSetUserName, ipmi::Privilege::Admin,
658 ipmiSetUserName);
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530659
Vernon Mauery7a3296d2021-08-05 11:08:23 -0700660 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
661 ipmi::app::cmdSetUserPasswordCommand,
662 ipmi::Privilege::Admin, ipmiSetUserPassword);
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530663
smritic46f6cd2019-03-20 14:09:41 +0530664 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
665 ipmi::app::cmdGetChannelAuthCapabilities,
666 ipmi::Privilege::Callback,
667 ipmiGetChannelAuthenticationCapabilities);
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000668
669 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
670 ipmi::app::cmdSetUserPayloadAccess,
671 ipmi::Privilege::Admin, ipmiSetUserPayloadAccess);
672
673 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
674 ipmi::app::cmdGetUserPayloadAccess,
675 ipmi::Privilege::Operator, ipmiGetUserPayloadAccess);
676
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530677 return;
678}
679} // namespace ipmi