blob: cc7174f2756c06af287d77a0c15901b364849ea7 [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 static constexpr ipmi::Cc ipmiCCPasswdFailMismatch = 0x80;
357 return ipmi::response(ipmiCCPasswdFailMismatch);
Richard Marian Thomaiyar282e79b2018-11-13 19:00:58 +0530358 }
Vernon Mauery7a3296d2021-08-05 11:08:23 -0700359 return ipmi::responseSuccess();
Richard Marian Thomaiyar282e79b2018-11-13 19:00:58 +0530360 }
Vernon Mauery7a3296d2021-08-05 11:08:23 -0700361 return ipmi::responseInvalidFieldRequest();
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530362}
363
smritic46f6cd2019-03-20 14:09:41 +0530364/** @brief implements the get channel authentication command
365 * @param ctx - IPMI context pointer (for channel)
366 * @param extData - get IPMI 2.0 extended data
367 * @param reserved1 - skip 3 bits
368 * @param chNum - channel number to get info about
369 * @param reserved2 - skip 4 bits
370 * @param privLevel - requested privilege level
371
372 * @returns ipmi completion code plus response data
373 * - channel number
374 * - rmcpAuthTypes - RMCP auth types (IPMI 1.5)
375 * - reserved1
376 * - extDataSupport - true for IPMI 2.0 extensions
377 * - anonymousLogin - true for anonymous login enabled
378 * - nullUsers - true for null user names enabled
379 * - nonNullUsers - true for non-null usernames enabled
380 * - userAuth - false for user authentication enabled
381 * - perMessageAuth - false for per message authentication enabled
382 * - KGStatus - true for Kg required for authentication
383 * - reserved2
384 * - rmcp - RMCP (IPMI 1.5) connection support
385 * - rmcpp - RMCP+ (IPMI 2.0) connection support
386 * - reserved3
387 * - oemID - OEM IANA of any OEM auth support
388 * - oemAuxillary - OEM data for auth
389 */
390ipmi::RspType<uint8_t, // channel number
391 uint6_t, // rmcpAuthTypes
392 bool, // reserved1
393 bool, // extDataSupport
394 bool, // anonymousLogin
395 bool, // nullUsers
396 bool, // nonNullUsers
397 bool, // userAuth
398 bool, // perMessageAuth
399 bool, // KGStatus
400 uint2_t, // reserved2
401 bool, // rmcp
402 bool, // rmcpp
403 uint6_t, // reserved3
404 uint24_t, // oemID
405 uint8_t // oemAuxillary
406 >
Patrick Williams1318a5e2024-08-16 15:19:54 -0400407 ipmiGetChannelAuthenticationCapabilities(
408 ipmi::Context::ptr ctx, uint4_t chNum, uint3_t reserved1,
409 [[maybe_unused]] bool extData, uint4_t privLevel, uint4_t reserved2)
smritic46f6cd2019-03-20 14:09:41 +0530410{
Patrick Williams1318a5e2024-08-16 15:19:54 -0400411 uint8_t channel =
412 convertCurrentChannelNum(static_cast<uint8_t>(chNum), ctx->channel);
smritic46f6cd2019-03-20 14:09:41 +0530413
414 if (reserved1 || reserved2 || !isValidChannel(channel) ||
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +0000415 !isValidPrivLimit(static_cast<uint8_t>(privLevel)))
smritic46f6cd2019-03-20 14:09:41 +0530416 {
George Liu82844ef2024-07-17 17:03:56 +0800417 lg2::debug("Get channel auth capabilities - Invalid field in request");
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +0000418 return ipmi::responseInvalidFieldRequest();
419 }
420
421 if (getChannelSessionSupport(channel) == EChannelSessSupported::none)
422 {
George Liu82844ef2024-07-17 17:03:56 +0800423 lg2::debug("Get channel auth capabilities - No support on channel");
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +0000424 return ipmi::response(ccActionNotSupportedForChannel);
smritic46f6cd2019-03-20 14:09:41 +0530425 }
426
427 constexpr bool extDataSupport = true; // true for IPMI 2.0 extensions
428 constexpr bool reserved3 = false;
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -0500429 constexpr uint6_t rmcpAuthTypes = 0; // IPMI 1.5 auth types - not supported
smritic46f6cd2019-03-20 14:09:41 +0530430 constexpr uint2_t reserved4 = 0;
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -0500431 constexpr bool KGStatus = false; // Not supporting now.
smritic46f6cd2019-03-20 14:09:41 +0530432 constexpr bool perMessageAuth = false; // Per message auth - enabled
433 constexpr bool userAuth = false; // User authentication - enabled
434 constexpr bool nullUsers = false; // Null user names - not supported
435 constexpr bool anonymousLogin = false; // Anonymous login - not supported
436 constexpr uint6_t reserved5 = 0;
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -0500437 constexpr bool rmcpp = true; // IPMI 2.0 - supported
438 constexpr bool rmcp = false; // IPMI 1.5 - not supported
smritic46f6cd2019-03-20 14:09:41 +0530439 constexpr uint24_t oemID = 0;
440 constexpr uint8_t oemAuxillary = 0;
441
442 bool nonNullUsers = 0;
443 uint8_t maxChUsers = 0, enabledUsers = 0, fixedUsers = 0;
444 ipmi::ipmiUserGetAllCounts(maxChUsers, enabledUsers, fixedUsers);
445 nonNullUsers = enabledUsers > 0;
446
447 return ipmi::responseSuccess(
448 channel, rmcpAuthTypes, reserved3, extDataSupport, anonymousLogin,
449 nullUsers, nonNullUsers, userAuth, perMessageAuth, KGStatus, reserved4,
450 rmcp, rmcpp, reserved5, oemID, oemAuxillary);
451}
452
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000453/** @brief implements the set user payload access command.
454 * @param ctx - IPMI context pointer (for channel)
455 * @param channel - channel number (4 bits)
456 * @param reserved1 - skip 4 bits
457 * @param userId - user id (6 bits)
458 * @param operation - access ENABLE /DISABLE. (2 bits)
459 * @param stdPayload0 - IPMI - reserved. (1 bit)
460 * @param stdPayload1 - SOL. (1 bit)
461 * @param stdPayload2 - (1 bit)
462 * @param stdPayload3 - (1 bit)
463 * @param stdPayload4 - (1 bit)
464 * @param stdPayload5 - (1 bit)
465 * @param stdPayload6 - (1 bit)
466 * @param stdPayload7 - (1 bit)
467 * @param stdPayloadEnables2Reserved - (8 bits)
468 * @param oemPayload0 - (1 bit)
469 * @param oemPayload1 - (1 bit)
470 * @param oemPayload2 - (1 bit)
471 * @param oemPayload3 - (1 bit)
472 * @param oemPayload4 - (1 bit)
473 * @param oemPayload5 - (1 bit)
474 * @param oemPayload6 - (1 bit)
475 * @param oemPayload7 - (1 bit)
476 * @param oemPayloadEnables2Reserved - (8 bits)
477 *
478 * @returns IPMI completion code
479 */
480ipmi::RspType<> ipmiSetUserPayloadAccess(
481 ipmi::Context::ptr ctx,
482
483 uint4_t channel, uint4_t reserved,
484
485 uint6_t userId, uint2_t operation,
486
487 bool stdPayload0ipmiReserved, bool stdPayload1SOL, bool stdPayload2,
488 bool stdPayload3, bool stdPayload4, bool stdPayload5, bool stdPayload6,
489 bool stdPayload7,
490
491 uint8_t stdPayloadEnables2Reserved,
492
493 bool oemPayload0, bool oemPayload1, bool oemPayload2, bool oemPayload3,
494 bool oemPayload4, bool oemPayload5, bool oemPayload6, bool oemPayload7,
495
496 uint8_t oemPayloadEnables2Reserved)
497{
Patrick Williams1318a5e2024-08-16 15:19:54 -0400498 auto chNum =
499 convertCurrentChannelNum(static_cast<uint8_t>(channel), ctx->channel);
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000500 // Validate the reserved args. Only SOL payload is supported as on date.
501 if (reserved || stdPayload0ipmiReserved || stdPayload2 || stdPayload3 ||
502 stdPayload4 || stdPayload5 || stdPayload6 || stdPayload7 ||
503 oemPayload0 || oemPayload1 || oemPayload2 || oemPayload3 ||
504 oemPayload4 || oemPayload5 || oemPayload6 || oemPayload7 ||
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +0000505 stdPayloadEnables2Reserved || oemPayloadEnables2Reserved ||
506 !isValidChannel(chNum))
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000507 {
508 return ipmi::responseInvalidFieldRequest();
509 }
510
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +0000511 if ((operation != enableOperation && operation != disableOperation))
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000512 {
513 return ipmi::responseInvalidFieldRequest();
514 }
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +0000515 if (getChannelSessionSupport(chNum) == EChannelSessSupported::none)
516 {
517 return ipmi::response(ccActionNotSupportedForChannel);
518 }
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000519 if (!ipmiUserIsValidUserId(static_cast<uint8_t>(userId)))
520 {
521 return ipmi::responseParmOutOfRange();
522 }
523
Willy Tu11d68892022-01-20 10:37:34 -0800524 PayloadAccess payloadAccess = {};
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000525 payloadAccess.stdPayloadEnables1[1] = stdPayload1SOL;
526
527 return ipmi::response(ipmiUserSetUserPayloadAccess(
528 chNum, static_cast<uint8_t>(operation), static_cast<uint8_t>(userId),
529 payloadAccess));
530}
531
532/** @brief implements the get user payload access command
533 * This command returns information about user payload enable settings
534 * that were set using the 'Set User Payload Access' Command.
535 *
536 * @param ctx - IPMI context pointer (for channel)
537 * @param channel - channel number
538 * @param reserved1 - skip 4 bits
539 * @param userId - user id
540 * @param reserved2 - skip 2 bits
541 *
542 * @returns IPMI completion code plus response data
543 * - stdPayload0ipmiReserved - IPMI payload (reserved).
544 * - stdPayload1SOL - SOL payload
545 * - stdPayload2
546 * - stdPayload3
547 * - stdPayload4
548 * - stdPayload5
549 * - stdPayload6
550 * - stdPayload7
551
552 * - stdPayloadEnables2Reserved - Reserved.
553
554 * - oemPayload0
555 * - oemPayload1
556 * - oemPayload2
557 * - oemPayload3
558 * - oemPayload4
559 * - oemPayload5
560 * - oemPayload6
561 * - oemPayload7
562
563 * - oemPayloadEnables2Reserved - Reserved
564 */
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -0500565ipmi::RspType<bool, // stdPayload0ipmiReserved
566 bool, // stdPayload1SOL
567 bool, // stdPayload2
568 bool, // stdPayload3
569 bool, // stdPayload4
570 bool, // stdPayload5
571 bool, // stdPayload6
572 bool, // stdPayload7
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000573
574 uint8_t, // stdPayloadEnables2Reserved
575
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -0500576 bool, // oemPayload0
577 bool, // oemPayload1
578 bool, // oemPayload2
579 bool, // oemPayload3
580 bool, // oemPayload4
581 bool, // oemPayload5
582 bool, // oemPayload6
583 bool, // oemPayload7
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000584
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -0500585 uint8_t // oemPayloadEnables2Reserved
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000586 >
587 ipmiGetUserPayloadAccess(ipmi::Context::ptr ctx,
588
589 uint4_t channel, uint4_t reserved1,
590
591 uint6_t userId, uint2_t reserved2)
592{
Patrick Williams1318a5e2024-08-16 15:19:54 -0400593 uint8_t chNum =
594 convertCurrentChannelNum(static_cast<uint8_t>(channel), ctx->channel);
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +0000595
596 if (reserved1 || reserved2 || !isValidChannel(chNum))
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000597 {
598 return ipmi::responseInvalidFieldRequest();
599 }
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +0000600 if (getChannelSessionSupport(chNum) == EChannelSessSupported::none)
601 {
602 return ipmi::response(ccActionNotSupportedForChannel);
603 }
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000604 if (!ipmiUserIsValidUserId(static_cast<uint8_t>(userId)))
605 {
606 return ipmi::responseParmOutOfRange();
607 }
608
609 ipmi::Cc retStatus;
610 PayloadAccess payloadAccess = {};
611 retStatus = ipmiUserGetUserPayloadAccess(
612 chNum, static_cast<uint8_t>(userId), payloadAccess);
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000613 if (retStatus != ccSuccess)
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000614 {
615 return ipmi::response(retStatus);
616 }
617 constexpr uint8_t res8bits = 0;
Patrick Williams1318a5e2024-08-16 15:19:54 -0400618 return ipmi::responseSuccess(
619 payloadAccess.stdPayloadEnables1.test(0),
620 payloadAccess.stdPayloadEnables1.test(1),
621 payloadAccess.stdPayloadEnables1.test(2),
622 payloadAccess.stdPayloadEnables1.test(3),
623 payloadAccess.stdPayloadEnables1.test(4),
624 payloadAccess.stdPayloadEnables1.test(5),
625 payloadAccess.stdPayloadEnables1.test(6),
626 payloadAccess.stdPayloadEnables1.test(7),
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000627
Patrick Williams1318a5e2024-08-16 15:19:54 -0400628 res8bits,
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000629
Patrick Williams1318a5e2024-08-16 15:19:54 -0400630 payloadAccess.oemPayloadEnables1.test(0),
631 payloadAccess.oemPayloadEnables1.test(1),
632 payloadAccess.oemPayloadEnables1.test(2),
633 payloadAccess.oemPayloadEnables1.test(3),
634 payloadAccess.oemPayloadEnables1.test(4),
635 payloadAccess.oemPayloadEnables1.test(5),
636 payloadAccess.oemPayloadEnables1.test(6),
637 payloadAccess.oemPayloadEnables1.test(7),
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000638
Patrick Williams1318a5e2024-08-16 15:19:54 -0400639 res8bits);
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000640}
641
William A. Kennington III343d0612018-12-10 15:56:24 -0800642void registerUserIpmiFunctions() __attribute__((constructor));
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530643void registerUserIpmiFunctions()
644{
Richard Marian Thomaiyar0be80bd2020-01-10 12:20:16 +0530645 post_work([]() { ipmiUserInit(); });
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530646 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
647 ipmi::app::cmdSetUserAccessCommand,
648 ipmi::Privilege::Admin, ipmiSetUserAccess);
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530649
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530650 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
651 ipmi::app::cmdGetUserAccessCommand,
ankita prasadbd604762023-01-18 10:56:43 +0000652 ipmi::Privilege::Admin, ipmiGetUserAccess);
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530653
Vernon Mauery3c89de12021-08-05 11:08:23 -0700654 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
655 ipmi::app::cmdGetUserNameCommand,
ankita prasadbd604762023-01-18 10:56:43 +0000656 ipmi::Privilege::Admin, ipmiGetUserName);
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530657
Vernon Maueryac30b392021-08-05 11:08:23 -0700658 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
659 ipmi::app::cmdSetUserName, ipmi::Privilege::Admin,
660 ipmiSetUserName);
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530661
Vernon Mauery7a3296d2021-08-05 11:08:23 -0700662 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
663 ipmi::app::cmdSetUserPasswordCommand,
664 ipmi::Privilege::Admin, ipmiSetUserPassword);
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530665
smritic46f6cd2019-03-20 14:09:41 +0530666 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
667 ipmi::app::cmdGetChannelAuthCapabilities,
668 ipmi::Privilege::Callback,
669 ipmiGetChannelAuthenticationCapabilities);
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000670
671 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
672 ipmi::app::cmdSetUserPayloadAccess,
673 ipmi::Privilege::Admin, ipmiSetUserPayloadAccess);
674
675 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
676 ipmi::app::cmdGetUserPayloadAccess,
677 ipmi::Privilege::Operator, ipmiGetUserPayloadAccess);
678
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530679 return;
680}
681} // namespace ipmi