blob: 4ea8c4bed64dd4683dbc673e8ede1772b25b4e4e [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>
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +053026#include <phosphor-logging/log.hpp>
27#include <regex>
28
29namespace ipmi
30{
31
32using namespace phosphor::logging;
33
Saravanan Palanisamy77381f12019-05-15 22:33:17 +000034static constexpr uint8_t enableOperation = 0x00;
35static constexpr uint8_t disableOperation = 0x01;
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +053036
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +053037/** @brief implements the set user access command
38 * @param ctx - IPMI context pointer (for channel)
39 * @param channel - channel number
40 * @param ipmiEnabled - indicates ipmi messaging state
41 * @param linkAuthEnabled - indicates link authentication state
42 * @param accessCallback - indicates callback state
43 * @param bitsUpdate - indicates update request
44 * @param userId - user id
45 * @param reserved1 - skip 2 bits
46 * @param privilege - user privilege
47 * @param reserved2 - skip 4 bits
48 * @param sessionLimit - optional - unused for now
49 *
50 * @returns ipmi completion code
51 */
52ipmi::RspType<> ipmiSetUserAccess(ipmi::Context::ptr ctx, uint4_t channel,
53 uint1_t ipmiEnabled, uint1_t linkAuthEnabled,
54 uint1_t accessCallback, uint1_t bitsUpdate,
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +053055
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +053056 uint6_t userId, uint2_t reserved1,
57
58 uint4_t privilege, uint4_t reserved2,
59
60 std::optional<uint8_t> sessionLimit)
61{
62 uint8_t sessLimit = sessionLimit.value_or(0);
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +000063 if (reserved1 || reserved2 || sessLimit ||
64 !ipmiUserIsValidPrivilege(static_cast<uint8_t>(privilege)))
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +053065 {
66 log<level::DEBUG>("Set user access - Invalid field in request");
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +053067 return ipmi::responseInvalidFieldRequest();
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +053068 }
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +000069
70 uint8_t chNum =
71 convertCurrentChannelNum(static_cast<uint8_t>(channel), ctx->channel);
72 if (!isValidChannel(chNum))
73 {
74 log<level::DEBUG>("Set user access - Invalid channel request");
75 return ipmi::response(invalidChannel);
76 }
77 if (getChannelSessionSupport(chNum) == EChannelSessSupported::none)
78 {
79 log<level::DEBUG>("Set user access - No support on channel");
80 return ipmi::response(ccActionNotSupportedForChannel);
81 }
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +053082 if (!ipmiUserIsValidUserId(static_cast<uint8_t>(userId)))
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +053083 {
84 log<level::DEBUG>("Set user access - Parameter out of range");
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +053085 return ipmi::responseParmOutOfRange();
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +053086 }
Richard Marian Thomaiyar06df8762018-12-08 17:38:25 +053087
Willy Tu11d68892022-01-20 10:37:34 -080088 PrivAccess privAccess = {};
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +053089 if (bitsUpdate)
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +053090 {
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +053091 privAccess.ipmiEnabled = static_cast<uint8_t>(ipmiEnabled);
92 privAccess.linkAuthEnabled = static_cast<uint8_t>(linkAuthEnabled);
93 privAccess.accessCallback = static_cast<uint8_t>(accessCallback);
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +053094 }
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +053095 privAccess.privilege = static_cast<uint8_t>(privilege);
96 return ipmi::response(
97 ipmiUserSetPrivilegeAccess(static_cast<uint8_t>(userId), chNum,
98 privAccess, static_cast<bool>(bitsUpdate)));
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +053099}
100
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530101/** @brief implements the set user access command
102 * @param ctx - IPMI context pointer (for channel)
103 * @param channel - channel number
104 * @param reserved1 - skip 4 bits
105 * @param userId - user id
106 * @param reserved2 - skip 2 bits
107 *
108 * @returns ipmi completion code plus response data
109 * - maxChUsers - max channel users
110 * - reserved1 - skip 2 bits
111 * - enabledUsers - enabled users count
112 * - enabledStatus - enabled status
113 * - fixedUsers - fixed users count
114 * - reserved2 - skip 2 bits
115 * - privilege - user privilege
116 * - ipmiEnabled - ipmi messaging state
117 * - linkAuthEnabled - link authenticatin state
118 * - accessCallback - callback state
119 * - reserved - skip 1 bit
120 */
121ipmi::RspType<uint6_t, // max channel users
122 uint2_t, // reserved1
123
124 uint6_t, // enabled users count
125 uint2_t, // enabled status
126
127 uint6_t, // fixed users count
128 uint2_t, // reserved2
129
130 uint4_t, // privilege
131 uint1_t, // ipmi messaging state
132 uint1_t, // link authentication state
133 uint1_t, // access callback state
134 uint1_t // reserved3
135 >
136 ipmiGetUserAccess(ipmi::Context::ptr ctx, uint4_t channel,
137 uint4_t reserved1,
138
139 uint6_t userId, uint2_t reserved2)
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530140{
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530141 uint8_t chNum =
Vernon Mauery5ed39592019-05-14 09:16:53 -0700142 convertCurrentChannelNum(static_cast<uint8_t>(channel), ctx->channel);
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +0000143
144 if (reserved1 || reserved2 || !isValidChannel(chNum))
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530145 {
146 log<level::DEBUG>("Get user access - Invalid field in request");
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530147 return ipmi::responseInvalidFieldRequest();
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530148 }
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +0000149
150 if (getChannelSessionSupport(chNum) == EChannelSessSupported::none)
151 {
152 log<level::DEBUG>("Get user access - No support on channel");
153 return ipmi::response(ccActionNotSupportedForChannel);
154 }
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530155 if (!ipmiUserIsValidUserId(static_cast<uint8_t>(userId)))
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530156 {
157 log<level::DEBUG>("Get user access - Parameter out of range");
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530158 return ipmi::responseParmOutOfRange();
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530159 }
160
161 uint8_t maxChUsers = 0, enabledUsers = 0, fixedUsers = 0;
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530162 ipmi::Cc retStatus;
Richard Marian Thomaiyarb6771e02019-01-29 14:42:44 +0530163 retStatus = ipmiUserGetAllCounts(maxChUsers, enabledUsers, fixedUsers);
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000164 if (retStatus != ccSuccess)
Richard Marian Thomaiyarb6771e02019-01-29 14:42:44 +0530165 {
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530166 return ipmi::response(retStatus);
Richard Marian Thomaiyarb6771e02019-01-29 14:42:44 +0530167 }
168
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530169 bool enabledState = false;
170 retStatus =
171 ipmiUserCheckEnabled(static_cast<uint8_t>(userId), enabledState);
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000172 if (retStatus != ccSuccess)
Richard Marian Thomaiyarb6771e02019-01-29 14:42:44 +0530173 {
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530174 return ipmi::response(retStatus);
Richard Marian Thomaiyarb6771e02019-01-29 14:42:44 +0530175 }
176
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530177 uint2_t enabledStatus = enabledState ? userIdEnabledViaSetPassword
178 : userIdDisabledViaSetPassword;
179 PrivAccess privAccess{};
180 retStatus = ipmiUserGetPrivilegeAccess(static_cast<uint8_t>(userId), chNum,
181 privAccess);
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000182 if (retStatus != ccSuccess)
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530183 {
184 return ipmi::response(retStatus);
185 }
186 constexpr uint2_t res2Bits = 0;
187 return ipmi::responseSuccess(
188 static_cast<uint6_t>(maxChUsers), res2Bits,
189
190 static_cast<uint6_t>(enabledUsers), enabledStatus,
191
192 static_cast<uint6_t>(fixedUsers), res2Bits,
193
194 static_cast<uint4_t>(privAccess.privilege),
195 static_cast<uint1_t>(privAccess.ipmiEnabled),
196 static_cast<uint1_t>(privAccess.linkAuthEnabled),
197 static_cast<uint1_t>(privAccess.accessCallback),
198 static_cast<uint1_t>(privAccess.reserved));
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530199}
200
Vernon Maueryac30b392021-08-05 11:08:23 -0700201/** @brief implementes the get user name command
202 * @param[in] ctx - ipmi command context
203 * @param[in] userId - 6-bit user ID
204 * @param[in] reserved - 2-bits reserved
205 * @param[in] name - 16-byte array for username
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530206
Vernon Maueryac30b392021-08-05 11:08:23 -0700207 * @returns ipmi response
208 */
209ipmi::RspType<>
Willy Tu11d68892022-01-20 10:37:34 -0800210 ipmiSetUserName([[maybe_unused]] ipmi::Context::ptr ctx, uint6_t id,
211 uint2_t reserved,
Vernon Maueryac30b392021-08-05 11:08:23 -0700212 const std::array<uint8_t, ipmi::ipmiMaxUserName>& name)
213{
214 if (reserved)
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530215 {
Vernon Maueryac30b392021-08-05 11:08:23 -0700216 return ipmi::responseInvalidFieldRequest();
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530217 }
Vernon Maueryac30b392021-08-05 11:08:23 -0700218 uint8_t userId = static_cast<uint8_t>(id);
219 if (!ipmiUserIsValidUserId(userId))
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530220 {
221 log<level::DEBUG>("Set user name - Invalid user id");
Vernon Maueryac30b392021-08-05 11:08:23 -0700222 return ipmi::responseParmOutOfRange();
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530223 }
224
Vernon Maueryac30b392021-08-05 11:08:23 -0700225 size_t nameLen = strnlen(reinterpret_cast<const char*>(name.data()),
226 ipmi::ipmiMaxUserName);
227 const std::string strUserName(reinterpret_cast<const char*>(name.data()),
jayaprakash Mutyalacdcdf2b2020-03-28 00:12:05 +0000228 nameLen);
229
Vernon Maueryac30b392021-08-05 11:08:23 -0700230 ipmi::Cc res = ipmiUserSetUserName(userId, strUserName);
231 return ipmi::response(res);
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530232}
233
234/** @brief implementes the get user name command
Vernon Mauery3c89de12021-08-05 11:08:23 -0700235 * @param[in] ctx - ipmi command context
236 * @param[in] userId - 6-bit user ID
237 * @param[in] reserved - 2-bits reserved
238
239 * @returns ipmi response with 16-byte username
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530240 */
Vernon Mauery3c89de12021-08-05 11:08:23 -0700241ipmi::RspType<std::array<uint8_t, ipmi::ipmiMaxUserName>> // user name
Willy Tu11d68892022-01-20 10:37:34 -0800242 ipmiGetUserName([[maybe_unused]] ipmi::Context::ptr ctx, uint6_t id,
243 uint2_t reserved)
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530244{
Vernon Mauery3c89de12021-08-05 11:08:23 -0700245 if (reserved)
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530246 {
Vernon Mauery3c89de12021-08-05 11:08:23 -0700247 return ipmi::responseInvalidFieldRequest();
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530248 }
249
Vernon Mauery3c89de12021-08-05 11:08:23 -0700250 uint8_t userId = static_cast<uint8_t>(id);
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530251 std::string userName;
Vernon Mauery3c89de12021-08-05 11:08:23 -0700252 if (ipmiUserGetUserName(userId, userName) != ccSuccess)
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530253 { // Invalid User ID
Vernon Mauery3c89de12021-08-05 11:08:23 -0700254 log<level::DEBUG>("User Name not found", entry("USER-ID=%u", userId));
255 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 {
282 log<level::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 {
297 log<level::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 {
Vernon Mauery7a3296d2021-08-05 11:08:23 -0700307 log<level::DEBUG>("User Name not found", entry("USER-ID=%d", userId));
308 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 {
Vernon Mauery7a3296d2021-08-05 11:08:23 -0700321 ipmi::Cc res =
322 ipmiUserUpdateEnabledState(userId, static_cast<bool>(operation));
323 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 {
354 log<level::DEBUG>("Test password failed",
Vernon Mauery7a3296d2021-08-05 11:08:23 -0700355 entry("USER-ID=%d", userId));
356 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 >
407 ipmiGetChannelAuthenticationCapabilities(ipmi::Context::ptr ctx,
408 uint4_t chNum, uint3_t reserved1,
Willy Tu11d68892022-01-20 10:37:34 -0800409 [[maybe_unused]] bool extData,
410 uint4_t privLevel,
smritic46f6cd2019-03-20 14:09:41 +0530411 uint4_t reserved2)
412{
smritic46f6cd2019-03-20 14:09:41 +0530413 uint8_t channel =
Vernon Mauery5ed39592019-05-14 09:16:53 -0700414 convertCurrentChannelNum(static_cast<uint8_t>(chNum), ctx->channel);
smritic46f6cd2019-03-20 14:09:41 +0530415
416 if (reserved1 || reserved2 || !isValidChannel(channel) ||
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +0000417 !isValidPrivLimit(static_cast<uint8_t>(privLevel)))
smritic46f6cd2019-03-20 14:09:41 +0530418 {
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +0000419 log<level::DEBUG>(
420 "Get channel auth capabilities - Invalid field in request");
421 return ipmi::responseInvalidFieldRequest();
422 }
423
424 if (getChannelSessionSupport(channel) == EChannelSessSupported::none)
425 {
426 log<level::DEBUG>(
427 "Get channel auth capabilities - No support on channel");
428 return ipmi::response(ccActionNotSupportedForChannel);
smritic46f6cd2019-03-20 14:09:41 +0530429 }
430
431 constexpr bool extDataSupport = true; // true for IPMI 2.0 extensions
432 constexpr bool reserved3 = false;
433 constexpr uint6_t rmcpAuthTypes = 0; // IPMI 1.5 auth types - not supported
434 constexpr uint2_t reserved4 = 0;
435 constexpr bool KGStatus = false; // Not supporting now.
436 constexpr bool perMessageAuth = false; // Per message auth - enabled
437 constexpr bool userAuth = false; // User authentication - enabled
438 constexpr bool nullUsers = false; // Null user names - not supported
439 constexpr bool anonymousLogin = false; // Anonymous login - not supported
440 constexpr uint6_t reserved5 = 0;
441 constexpr bool rmcpp = true; // IPMI 2.0 - supported
442 constexpr bool rmcp = false; // IPMI 1.5 - not supported
443 constexpr uint24_t oemID = 0;
444 constexpr uint8_t oemAuxillary = 0;
445
446 bool nonNullUsers = 0;
447 uint8_t maxChUsers = 0, enabledUsers = 0, fixedUsers = 0;
448 ipmi::ipmiUserGetAllCounts(maxChUsers, enabledUsers, fixedUsers);
449 nonNullUsers = enabledUsers > 0;
450
451 return ipmi::responseSuccess(
452 channel, rmcpAuthTypes, reserved3, extDataSupport, anonymousLogin,
453 nullUsers, nonNullUsers, userAuth, perMessageAuth, KGStatus, reserved4,
454 rmcp, rmcpp, reserved5, oemID, oemAuxillary);
455}
456
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000457/** @brief implements the set user payload access command.
458 * @param ctx - IPMI context pointer (for channel)
459 * @param channel - channel number (4 bits)
460 * @param reserved1 - skip 4 bits
461 * @param userId - user id (6 bits)
462 * @param operation - access ENABLE /DISABLE. (2 bits)
463 * @param stdPayload0 - IPMI - reserved. (1 bit)
464 * @param stdPayload1 - SOL. (1 bit)
465 * @param stdPayload2 - (1 bit)
466 * @param stdPayload3 - (1 bit)
467 * @param stdPayload4 - (1 bit)
468 * @param stdPayload5 - (1 bit)
469 * @param stdPayload6 - (1 bit)
470 * @param stdPayload7 - (1 bit)
471 * @param stdPayloadEnables2Reserved - (8 bits)
472 * @param oemPayload0 - (1 bit)
473 * @param oemPayload1 - (1 bit)
474 * @param oemPayload2 - (1 bit)
475 * @param oemPayload3 - (1 bit)
476 * @param oemPayload4 - (1 bit)
477 * @param oemPayload5 - (1 bit)
478 * @param oemPayload6 - (1 bit)
479 * @param oemPayload7 - (1 bit)
480 * @param oemPayloadEnables2Reserved - (8 bits)
481 *
482 * @returns IPMI completion code
483 */
484ipmi::RspType<> ipmiSetUserPayloadAccess(
485 ipmi::Context::ptr ctx,
486
487 uint4_t channel, uint4_t reserved,
488
489 uint6_t userId, uint2_t operation,
490
491 bool stdPayload0ipmiReserved, bool stdPayload1SOL, bool stdPayload2,
492 bool stdPayload3, bool stdPayload4, bool stdPayload5, bool stdPayload6,
493 bool stdPayload7,
494
495 uint8_t stdPayloadEnables2Reserved,
496
497 bool oemPayload0, bool oemPayload1, bool oemPayload2, bool oemPayload3,
498 bool oemPayload4, bool oemPayload5, bool oemPayload6, bool oemPayload7,
499
500 uint8_t oemPayloadEnables2Reserved)
501{
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +0000502 auto chNum =
503 convertCurrentChannelNum(static_cast<uint8_t>(channel), ctx->channel);
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000504 // Validate the reserved args. Only SOL payload is supported as on date.
505 if (reserved || stdPayload0ipmiReserved || stdPayload2 || stdPayload3 ||
506 stdPayload4 || stdPayload5 || stdPayload6 || stdPayload7 ||
507 oemPayload0 || oemPayload1 || oemPayload2 || oemPayload3 ||
508 oemPayload4 || oemPayload5 || oemPayload6 || oemPayload7 ||
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +0000509 stdPayloadEnables2Reserved || oemPayloadEnables2Reserved ||
510 !isValidChannel(chNum))
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000511 {
512 return ipmi::responseInvalidFieldRequest();
513 }
514
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +0000515 if ((operation != enableOperation && operation != disableOperation))
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000516 {
517 return ipmi::responseInvalidFieldRequest();
518 }
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +0000519 if (getChannelSessionSupport(chNum) == EChannelSessSupported::none)
520 {
521 return ipmi::response(ccActionNotSupportedForChannel);
522 }
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000523 if (!ipmiUserIsValidUserId(static_cast<uint8_t>(userId)))
524 {
525 return ipmi::responseParmOutOfRange();
526 }
527
Willy Tu11d68892022-01-20 10:37:34 -0800528 PayloadAccess payloadAccess = {};
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000529 payloadAccess.stdPayloadEnables1[1] = stdPayload1SOL;
530
531 return ipmi::response(ipmiUserSetUserPayloadAccess(
532 chNum, static_cast<uint8_t>(operation), static_cast<uint8_t>(userId),
533 payloadAccess));
534}
535
536/** @brief implements the get user payload access command
537 * This command returns information about user payload enable settings
538 * that were set using the 'Set User Payload Access' Command.
539 *
540 * @param ctx - IPMI context pointer (for channel)
541 * @param channel - channel number
542 * @param reserved1 - skip 4 bits
543 * @param userId - user id
544 * @param reserved2 - skip 2 bits
545 *
546 * @returns IPMI completion code plus response data
547 * - stdPayload0ipmiReserved - IPMI payload (reserved).
548 * - stdPayload1SOL - SOL payload
549 * - stdPayload2
550 * - stdPayload3
551 * - stdPayload4
552 * - stdPayload5
553 * - stdPayload6
554 * - stdPayload7
555
556 * - stdPayloadEnables2Reserved - Reserved.
557
558 * - oemPayload0
559 * - oemPayload1
560 * - oemPayload2
561 * - oemPayload3
562 * - oemPayload4
563 * - oemPayload5
564 * - oemPayload6
565 * - oemPayload7
566
567 * - oemPayloadEnables2Reserved - Reserved
568 */
569ipmi::RspType<bool, // stdPayload0ipmiReserved
570 bool, // stdPayload1SOL
571 bool, // stdPayload2
572 bool, // stdPayload3
573 bool, // stdPayload4
574 bool, // stdPayload5
575 bool, // stdPayload6
576 bool, // stdPayload7
577
578 uint8_t, // stdPayloadEnables2Reserved
579
580 bool, // oemPayload0
581 bool, // oemPayload1
582 bool, // oemPayload2
583 bool, // oemPayload3
584 bool, // oemPayload4
585 bool, // oemPayload5
586 bool, // oemPayload6
587 bool, // oemPayload7
588
589 uint8_t // oemPayloadEnables2Reserved
590 >
591 ipmiGetUserPayloadAccess(ipmi::Context::ptr ctx,
592
593 uint4_t channel, uint4_t reserved1,
594
595 uint6_t userId, uint2_t reserved2)
596{
597 uint8_t chNum =
598 convertCurrentChannelNum(static_cast<uint8_t>(channel), ctx->channel);
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +0000599
600 if (reserved1 || reserved2 || !isValidChannel(chNum))
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000601 {
602 return ipmi::responseInvalidFieldRequest();
603 }
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +0000604 if (getChannelSessionSupport(chNum) == EChannelSessSupported::none)
605 {
606 return ipmi::response(ccActionNotSupportedForChannel);
607 }
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000608 if (!ipmiUserIsValidUserId(static_cast<uint8_t>(userId)))
609 {
610 return ipmi::responseParmOutOfRange();
611 }
612
613 ipmi::Cc retStatus;
614 PayloadAccess payloadAccess = {};
615 retStatus = ipmiUserGetUserPayloadAccess(
616 chNum, static_cast<uint8_t>(userId), payloadAccess);
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000617 if (retStatus != ccSuccess)
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000618 {
619 return ipmi::response(retStatus);
620 }
621 constexpr uint8_t res8bits = 0;
622 return ipmi::responseSuccess(payloadAccess.stdPayloadEnables1.test(0),
623 payloadAccess.stdPayloadEnables1.test(1),
624 payloadAccess.stdPayloadEnables1.test(2),
625 payloadAccess.stdPayloadEnables1.test(3),
626 payloadAccess.stdPayloadEnables1.test(4),
627 payloadAccess.stdPayloadEnables1.test(5),
628 payloadAccess.stdPayloadEnables1.test(6),
629 payloadAccess.stdPayloadEnables1.test(7),
630
631 res8bits,
632
633 payloadAccess.oemPayloadEnables1.test(0),
634 payloadAccess.oemPayloadEnables1.test(1),
635 payloadAccess.oemPayloadEnables1.test(2),
636 payloadAccess.oemPayloadEnables1.test(3),
637 payloadAccess.oemPayloadEnables1.test(4),
638 payloadAccess.oemPayloadEnables1.test(5),
639 payloadAccess.oemPayloadEnables1.test(6),
640 payloadAccess.oemPayloadEnables1.test(7),
641
642 res8bits);
643}
644
William A. Kennington III343d0612018-12-10 15:56:24 -0800645void registerUserIpmiFunctions() __attribute__((constructor));
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530646void registerUserIpmiFunctions()
647{
Richard Marian Thomaiyar0be80bd2020-01-10 12:20:16 +0530648 post_work([]() { ipmiUserInit(); });
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530649 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
650 ipmi::app::cmdSetUserAccessCommand,
651 ipmi::Privilege::Admin, ipmiSetUserAccess);
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530652
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530653 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
654 ipmi::app::cmdGetUserAccessCommand,
ankita prasadbd604762023-01-18 10:56:43 +0000655 ipmi::Privilege::Admin, ipmiGetUserAccess);
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530656
Vernon Mauery3c89de12021-08-05 11:08:23 -0700657 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
658 ipmi::app::cmdGetUserNameCommand,
ankita prasadbd604762023-01-18 10:56:43 +0000659 ipmi::Privilege::Admin, ipmiGetUserName);
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530660
Vernon Maueryac30b392021-08-05 11:08:23 -0700661 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
662 ipmi::app::cmdSetUserName, ipmi::Privilege::Admin,
663 ipmiSetUserName);
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530664
Vernon Mauery7a3296d2021-08-05 11:08:23 -0700665 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
666 ipmi::app::cmdSetUserPasswordCommand,
667 ipmi::Privilege::Admin, ipmiSetUserPassword);
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530668
smritic46f6cd2019-03-20 14:09:41 +0530669 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
670 ipmi::app::cmdGetChannelAuthCapabilities,
671 ipmi::Privilege::Callback,
672 ipmiGetChannelAuthenticationCapabilities);
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000673
674 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
675 ipmi::app::cmdSetUserPayloadAccess,
676 ipmi::Privilege::Admin, ipmiSetUserPayloadAccess);
677
678 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
679 ipmi::app::cmdGetUserPayloadAccess,
680 ipmi::Privilege::Operator, ipmiGetUserPayloadAccess);
681
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530682 return;
683}
684} // namespace ipmi