blob: 630a36398af04f3b736019307f3151f358af12dc [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
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +053034static constexpr uint8_t disableUser = 0x00;
35static constexpr uint8_t enableUser = 0x01;
36static constexpr uint8_t setPassword = 0x02;
37static constexpr uint8_t testPassword = 0x03;
Richard Marian Thomaiyar23df06f2019-01-04 16:42:22 +053038static constexpr uint8_t passwordKeySize20 = 1;
39static constexpr uint8_t passwordKeySize16 = 0;
Saravanan Palanisamy77381f12019-05-15 22:33:17 +000040static constexpr uint8_t enableOperation = 0x00;
41static constexpr uint8_t disableOperation = 0x01;
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +053042
Richard Marian Thomaiyar6e1ba9e2018-11-29 06:29:21 +053043/** @struct SetUserNameReq
44 *
45 * Structure for set user name request command (refer spec sec 22.28)
46 */
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +053047struct SetUserNameReq
48{
49#if BYTE_ORDER == LITTLE_ENDIAN
50 uint8_t userId : 6;
51 uint8_t reserved1 : 2;
52#endif
53#if BYTE_ORDER == BIG_ENDIAN
54 uint8_t reserved1 : 2;
55 uint8_t userId : 6;
56#endif
57 uint8_t userName[16];
58} __attribute__((packed));
59
Richard Marian Thomaiyar6e1ba9e2018-11-29 06:29:21 +053060/** @struct SetUserPasswordReq
61 *
62 * Structure for set user password request command (refer spec sec 22.30)
63 */
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +053064struct SetUserPasswordReq
65{
66#if BYTE_ORDER == LITTLE_ENDIAN
67 uint8_t userId : 6;
68 uint8_t reserved1 : 1;
69 uint8_t ipmi20 : 1;
70 uint8_t operation : 2;
71 uint8_t reserved2 : 6;
72#endif
73#if BYTE_ORDER == BIG_ENDIAN
74 uint8_t ipmi20 : 1;
75 uint8_t reserved1 : 1;
76 uint8_t userId : 6;
77 uint8_t reserved2 : 6;
78 uint8_t operation : 2;
79#endif
80 uint8_t userPassword[maxIpmi20PasswordSize];
81} __attribute__((packed));
82
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +053083/** @brief implements the set user access command
84 * @param ctx - IPMI context pointer (for channel)
85 * @param channel - channel number
86 * @param ipmiEnabled - indicates ipmi messaging state
87 * @param linkAuthEnabled - indicates link authentication state
88 * @param accessCallback - indicates callback state
89 * @param bitsUpdate - indicates update request
90 * @param userId - user id
91 * @param reserved1 - skip 2 bits
92 * @param privilege - user privilege
93 * @param reserved2 - skip 4 bits
94 * @param sessionLimit - optional - unused for now
95 *
96 * @returns ipmi completion code
97 */
98ipmi::RspType<> ipmiSetUserAccess(ipmi::Context::ptr ctx, uint4_t channel,
99 uint1_t ipmiEnabled, uint1_t linkAuthEnabled,
100 uint1_t accessCallback, uint1_t bitsUpdate,
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530101
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530102 uint6_t userId, uint2_t reserved1,
103
104 uint4_t privilege, uint4_t reserved2,
105
106 std::optional<uint8_t> sessionLimit)
107{
108 uint8_t sessLimit = sessionLimit.value_or(0);
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +0000109 if (reserved1 || reserved2 || sessLimit ||
110 !ipmiUserIsValidPrivilege(static_cast<uint8_t>(privilege)))
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530111 {
112 log<level::DEBUG>("Set user access - Invalid field in request");
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530113 return ipmi::responseInvalidFieldRequest();
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530114 }
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +0000115
116 uint8_t chNum =
117 convertCurrentChannelNum(static_cast<uint8_t>(channel), ctx->channel);
118 if (!isValidChannel(chNum))
119 {
120 log<level::DEBUG>("Set user access - Invalid channel request");
121 return ipmi::response(invalidChannel);
122 }
123 if (getChannelSessionSupport(chNum) == EChannelSessSupported::none)
124 {
125 log<level::DEBUG>("Set user access - No support on channel");
126 return ipmi::response(ccActionNotSupportedForChannel);
127 }
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530128 if (!ipmiUserIsValidUserId(static_cast<uint8_t>(userId)))
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530129 {
130 log<level::DEBUG>("Set user access - Parameter out of range");
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530131 return ipmi::responseParmOutOfRange();
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530132 }
Richard Marian Thomaiyar06df8762018-12-08 17:38:25 +0530133
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530134 PrivAccess privAccess = {0};
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530135 if (bitsUpdate)
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530136 {
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530137 privAccess.ipmiEnabled = static_cast<uint8_t>(ipmiEnabled);
138 privAccess.linkAuthEnabled = static_cast<uint8_t>(linkAuthEnabled);
139 privAccess.accessCallback = static_cast<uint8_t>(accessCallback);
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530140 }
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530141 privAccess.privilege = static_cast<uint8_t>(privilege);
142 return ipmi::response(
143 ipmiUserSetPrivilegeAccess(static_cast<uint8_t>(userId), chNum,
144 privAccess, static_cast<bool>(bitsUpdate)));
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530145}
146
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530147/** @brief implements the set user access command
148 * @param ctx - IPMI context pointer (for channel)
149 * @param channel - channel number
150 * @param reserved1 - skip 4 bits
151 * @param userId - user id
152 * @param reserved2 - skip 2 bits
153 *
154 * @returns ipmi completion code plus response data
155 * - maxChUsers - max channel users
156 * - reserved1 - skip 2 bits
157 * - enabledUsers - enabled users count
158 * - enabledStatus - enabled status
159 * - fixedUsers - fixed users count
160 * - reserved2 - skip 2 bits
161 * - privilege - user privilege
162 * - ipmiEnabled - ipmi messaging state
163 * - linkAuthEnabled - link authenticatin state
164 * - accessCallback - callback state
165 * - reserved - skip 1 bit
166 */
167ipmi::RspType<uint6_t, // max channel users
168 uint2_t, // reserved1
169
170 uint6_t, // enabled users count
171 uint2_t, // enabled status
172
173 uint6_t, // fixed users count
174 uint2_t, // reserved2
175
176 uint4_t, // privilege
177 uint1_t, // ipmi messaging state
178 uint1_t, // link authentication state
179 uint1_t, // access callback state
180 uint1_t // reserved3
181 >
182 ipmiGetUserAccess(ipmi::Context::ptr ctx, uint4_t channel,
183 uint4_t reserved1,
184
185 uint6_t userId, uint2_t reserved2)
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530186{
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530187 uint8_t chNum =
Vernon Mauery5ed39592019-05-14 09:16:53 -0700188 convertCurrentChannelNum(static_cast<uint8_t>(channel), ctx->channel);
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +0000189
190 if (reserved1 || reserved2 || !isValidChannel(chNum))
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530191 {
192 log<level::DEBUG>("Get user access - Invalid field in request");
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530193 return ipmi::responseInvalidFieldRequest();
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530194 }
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +0000195
196 if (getChannelSessionSupport(chNum) == EChannelSessSupported::none)
197 {
198 log<level::DEBUG>("Get user access - No support on channel");
199 return ipmi::response(ccActionNotSupportedForChannel);
200 }
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530201 if (!ipmiUserIsValidUserId(static_cast<uint8_t>(userId)))
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530202 {
203 log<level::DEBUG>("Get user access - Parameter out of range");
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530204 return ipmi::responseParmOutOfRange();
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530205 }
206
207 uint8_t maxChUsers = 0, enabledUsers = 0, fixedUsers = 0;
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530208 ipmi::Cc retStatus;
Richard Marian Thomaiyarb6771e02019-01-29 14:42:44 +0530209 retStatus = ipmiUserGetAllCounts(maxChUsers, enabledUsers, fixedUsers);
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000210 if (retStatus != ccSuccess)
Richard Marian Thomaiyarb6771e02019-01-29 14:42:44 +0530211 {
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530212 return ipmi::response(retStatus);
Richard Marian Thomaiyarb6771e02019-01-29 14:42:44 +0530213 }
214
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530215 bool enabledState = false;
216 retStatus =
217 ipmiUserCheckEnabled(static_cast<uint8_t>(userId), enabledState);
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000218 if (retStatus != ccSuccess)
Richard Marian Thomaiyarb6771e02019-01-29 14:42:44 +0530219 {
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530220 return ipmi::response(retStatus);
Richard Marian Thomaiyarb6771e02019-01-29 14:42:44 +0530221 }
222
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530223 uint2_t enabledStatus = enabledState ? userIdEnabledViaSetPassword
224 : userIdDisabledViaSetPassword;
225 PrivAccess privAccess{};
226 retStatus = ipmiUserGetPrivilegeAccess(static_cast<uint8_t>(userId), chNum,
227 privAccess);
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000228 if (retStatus != ccSuccess)
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530229 {
230 return ipmi::response(retStatus);
231 }
232 constexpr uint2_t res2Bits = 0;
233 return ipmi::responseSuccess(
234 static_cast<uint6_t>(maxChUsers), res2Bits,
235
236 static_cast<uint6_t>(enabledUsers), enabledStatus,
237
238 static_cast<uint6_t>(fixedUsers), res2Bits,
239
240 static_cast<uint4_t>(privAccess.privilege),
241 static_cast<uint1_t>(privAccess.ipmiEnabled),
242 static_cast<uint1_t>(privAccess.linkAuthEnabled),
243 static_cast<uint1_t>(privAccess.accessCallback),
244 static_cast<uint1_t>(privAccess.reserved));
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530245}
246
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000247Cc ipmiSetUserName(ipmi_netfn_t netfn, ipmi_cmd_t cmd, ipmi_request_t request,
248 ipmi_response_t response, ipmi_data_len_t dataLen,
249 ipmi_context_t context)
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530250{
251 const SetUserNameReq* req = static_cast<SetUserNameReq*>(request);
252 size_t reqLength = *dataLen;
253 *dataLen = 0;
254
255 if (reqLength != sizeof(*req))
256 {
257 log<level::DEBUG>("Set user name - Invalid Length");
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000258 return ccReqDataLenInvalid;
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530259 }
260 if (req->reserved1)
261 {
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000262 return ccInvalidFieldRequest;
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530263 }
264 if (!ipmiUserIsValidUserId(req->userId))
265 {
266 log<level::DEBUG>("Set user name - Invalid user id");
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000267 return ccParmOutOfRange;
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530268 }
269
jayaprakash Mutyalacdcdf2b2020-03-28 00:12:05 +0000270 size_t nameLen = strnlen(reinterpret_cast<const char*>(req->userName),
271 sizeof(req->userName));
272 const std::string strUserName(reinterpret_cast<const char*>(req->userName),
273 nameLen);
274
275 return ipmiUserSetUserName(req->userId, strUserName);
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530276}
277
278/** @brief implementes the get user name command
Vernon Mauery3c89de12021-08-05 11:08:23 -0700279 * @param[in] ctx - ipmi command context
280 * @param[in] userId - 6-bit user ID
281 * @param[in] reserved - 2-bits reserved
282
283 * @returns ipmi response with 16-byte username
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530284 */
Vernon Mauery3c89de12021-08-05 11:08:23 -0700285ipmi::RspType<std::array<uint8_t, ipmi::ipmiMaxUserName>> // user name
286 ipmiGetUserName(ipmi::Context::ptr ctx, uint6_t id, uint2_t reserved)
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530287{
Vernon Mauery3c89de12021-08-05 11:08:23 -0700288 if (reserved)
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530289 {
Vernon Mauery3c89de12021-08-05 11:08:23 -0700290 return ipmi::responseInvalidFieldRequest();
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530291 }
292
Vernon Mauery3c89de12021-08-05 11:08:23 -0700293 uint8_t userId = static_cast<uint8_t>(id);
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530294 std::string userName;
Vernon Mauery3c89de12021-08-05 11:08:23 -0700295 if (ipmiUserGetUserName(userId, userName) != ccSuccess)
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530296 { // Invalid User ID
Vernon Mauery3c89de12021-08-05 11:08:23 -0700297 log<level::DEBUG>("User Name not found", entry("USER-ID=%u", userId));
298 return ipmi::responseParmOutOfRange();
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530299 }
Vernon Mauery3c89de12021-08-05 11:08:23 -0700300 // copy the std::string into a fixed array
301 if (userName.size() > ipmi::ipmiMaxUserName)
302 {
303 return ipmi::responseUnspecifiedError();
304 }
305 std::array<uint8_t, ipmi::ipmiMaxUserName> userNameFixed;
306 std::fill(userNameFixed.begin(), userNameFixed.end(), 0);
307 std::copy(userName.begin(), userName.end(), userNameFixed.begin());
308 return ipmi::responseSuccess(std::move(userNameFixed));
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530309}
310
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530311/** @brief implementes the set user password command
312 * @param[in] netfn - specifies netfn.
313 * @param[in] cmd - specifies cmd number.
314 * @param[in] request - pointer to request data.
315 * @param[in, out] dataLen - specifies request data length, and returns
316 * response data length.
317 * @param[in] context - ipmi context.
318 * @returns ipmi completion code.
319 */
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000320Cc ipmiSetUserPassword(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
321 ipmi_request_t request, ipmi_response_t response,
322 ipmi_data_len_t dataLen, ipmi_context_t context)
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530323{
324 const SetUserPasswordReq* req = static_cast<SetUserPasswordReq*>(request);
325 size_t reqLength = *dataLen;
326 // subtract 2 bytes header to know the password length - including NULL
327 uint8_t passwordLength = *dataLen - 2;
328 *dataLen = 0;
Snehalatha Venkatesh37b1d1a2021-06-28 10:13:37 +0000329 if (req->reserved1 || req->reserved2)
330 {
331 log<level::DEBUG>("Invalid data field in request");
332 return ccInvalidFieldRequest;
333 }
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530334
335 // verify input length based on operation. Required password size is 20
336 // bytes as we support only IPMI 2.0, but in order to be compatible with
337 // tools, accept 16 bytes of password size too.
338 if (reqLength < 2 ||
339 // If enable / disable user, reqLength has to be >=2 & <= 22
340 ((req->operation == disableUser || req->operation == enableUser) &&
341 ((reqLength < 2) || (reqLength > sizeof(SetUserPasswordReq)))))
342 {
343 log<level::DEBUG>("Invalid Length");
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000344 return ccReqDataLenInvalid;
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530345 }
346 // If set / test password then password length has to be 16 or 20 bytes
Richard Marian Thomaiyar23df06f2019-01-04 16:42:22 +0530347 // based on the password size bit.
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530348 if (((req->operation == setPassword) || (req->operation == testPassword)) &&
Richard Marian Thomaiyar23df06f2019-01-04 16:42:22 +0530349 (((req->ipmi20 == passwordKeySize20) &&
350 (passwordLength != maxIpmi20PasswordSize)) ||
351 ((req->ipmi20 == passwordKeySize16) &&
352 (passwordLength != maxIpmi15PasswordSize))))
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530353 {
354 log<level::DEBUG>("Invalid Length");
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000355 return ccReqDataLenInvalid;
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530356 }
357
358 std::string userName;
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000359 if (ipmiUserGetUserName(req->userId, userName) != ccSuccess)
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530360 {
361 log<level::DEBUG>("User Name not found",
Ayushi Smriti05ad3412019-10-16 16:10:18 +0530362 entry("USER-ID=%d", (uint8_t)req->userId));
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000363 return ccParmOutOfRange;
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530364 }
365 if (req->operation == setPassword)
366 {
Suryakanth Sekar90b00c72019-01-16 10:37:57 +0530367 return ipmiUserSetUserPassword(
368 req->userId, reinterpret_cast<const char*>(req->userPassword));
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530369 }
Richard Marian Thomaiyar282e79b2018-11-13 19:00:58 +0530370 else if (req->operation == enableUser || req->operation == disableUser)
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530371 {
Richard Marian Thomaiyar282e79b2018-11-13 19:00:58 +0530372 return ipmiUserUpdateEnabledState(req->userId,
373 static_cast<bool>(req->operation));
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530374 }
Richard Marian Thomaiyar282e79b2018-11-13 19:00:58 +0530375 else if (req->operation == testPassword)
376 {
377 auto password = ipmiUserGetPassword(userName);
378 std::string testPassword(
379 reinterpret_cast<const char*>(req->userPassword), 0,
380 passwordLength);
381 // Note: For security reasons password size won't be compared and
382 // wrong password size completion code will not be returned if size
383 // doesn't match as specified in IPMI specification.
384 if (password != testPassword)
385 {
386 log<level::DEBUG>("Test password failed",
Ayushi Smriti05ad3412019-10-16 16:10:18 +0530387 entry("USER-ID=%d", (uint8_t)req->userId));
Jayaprakash Mutyala70bd0632020-10-23 06:24:55 +0000388 // Clear sensitive data
gokulsankerd6d567a2021-07-23 19:36:46 +0530389 OPENSSL_cleanse(testPassword.data(), testPassword.length());
390 OPENSSL_cleanse(password.data(), password.length());
Jayaprakash Mutyala70bd0632020-10-23 06:24:55 +0000391
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000392 return static_cast<Cc>(
Richard Marian Thomaiyar282e79b2018-11-13 19:00:58 +0530393 IPMISetPasswordReturnCodes::ipmiCCPasswdFailMismatch);
394 }
Jayaprakash Mutyala70bd0632020-10-23 06:24:55 +0000395 // Clear sensitive data
gokulsankerd6d567a2021-07-23 19:36:46 +0530396 OPENSSL_cleanse(testPassword.data(), testPassword.length());
397 OPENSSL_cleanse(password.data(), password.length());
Jayaprakash Mutyala70bd0632020-10-23 06:24:55 +0000398
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000399 return ccSuccess;
Richard Marian Thomaiyar282e79b2018-11-13 19:00:58 +0530400 }
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000401 return ccInvalidFieldRequest;
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530402}
403
smritic46f6cd2019-03-20 14:09:41 +0530404/** @brief implements the get channel authentication command
405 * @param ctx - IPMI context pointer (for channel)
406 * @param extData - get IPMI 2.0 extended data
407 * @param reserved1 - skip 3 bits
408 * @param chNum - channel number to get info about
409 * @param reserved2 - skip 4 bits
410 * @param privLevel - requested privilege level
411
412 * @returns ipmi completion code plus response data
413 * - channel number
414 * - rmcpAuthTypes - RMCP auth types (IPMI 1.5)
415 * - reserved1
416 * - extDataSupport - true for IPMI 2.0 extensions
417 * - anonymousLogin - true for anonymous login enabled
418 * - nullUsers - true for null user names enabled
419 * - nonNullUsers - true for non-null usernames enabled
420 * - userAuth - false for user authentication enabled
421 * - perMessageAuth - false for per message authentication enabled
422 * - KGStatus - true for Kg required for authentication
423 * - reserved2
424 * - rmcp - RMCP (IPMI 1.5) connection support
425 * - rmcpp - RMCP+ (IPMI 2.0) connection support
426 * - reserved3
427 * - oemID - OEM IANA of any OEM auth support
428 * - oemAuxillary - OEM data for auth
429 */
430ipmi::RspType<uint8_t, // channel number
431 uint6_t, // rmcpAuthTypes
432 bool, // reserved1
433 bool, // extDataSupport
434 bool, // anonymousLogin
435 bool, // nullUsers
436 bool, // nonNullUsers
437 bool, // userAuth
438 bool, // perMessageAuth
439 bool, // KGStatus
440 uint2_t, // reserved2
441 bool, // rmcp
442 bool, // rmcpp
443 uint6_t, // reserved3
444 uint24_t, // oemID
445 uint8_t // oemAuxillary
446 >
447 ipmiGetChannelAuthenticationCapabilities(ipmi::Context::ptr ctx,
448 uint4_t chNum, uint3_t reserved1,
449 bool extData, uint4_t privLevel,
450 uint4_t reserved2)
451{
smritic46f6cd2019-03-20 14:09:41 +0530452 uint8_t channel =
Vernon Mauery5ed39592019-05-14 09:16:53 -0700453 convertCurrentChannelNum(static_cast<uint8_t>(chNum), ctx->channel);
smritic46f6cd2019-03-20 14:09:41 +0530454
455 if (reserved1 || reserved2 || !isValidChannel(channel) ||
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +0000456 !isValidPrivLimit(static_cast<uint8_t>(privLevel)))
smritic46f6cd2019-03-20 14:09:41 +0530457 {
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +0000458 log<level::DEBUG>(
459 "Get channel auth capabilities - Invalid field in request");
460 return ipmi::responseInvalidFieldRequest();
461 }
462
463 if (getChannelSessionSupport(channel) == EChannelSessSupported::none)
464 {
465 log<level::DEBUG>(
466 "Get channel auth capabilities - No support on channel");
467 return ipmi::response(ccActionNotSupportedForChannel);
smritic46f6cd2019-03-20 14:09:41 +0530468 }
469
470 constexpr bool extDataSupport = true; // true for IPMI 2.0 extensions
471 constexpr bool reserved3 = false;
472 constexpr uint6_t rmcpAuthTypes = 0; // IPMI 1.5 auth types - not supported
473 constexpr uint2_t reserved4 = 0;
474 constexpr bool KGStatus = false; // Not supporting now.
475 constexpr bool perMessageAuth = false; // Per message auth - enabled
476 constexpr bool userAuth = false; // User authentication - enabled
477 constexpr bool nullUsers = false; // Null user names - not supported
478 constexpr bool anonymousLogin = false; // Anonymous login - not supported
479 constexpr uint6_t reserved5 = 0;
480 constexpr bool rmcpp = true; // IPMI 2.0 - supported
481 constexpr bool rmcp = false; // IPMI 1.5 - not supported
482 constexpr uint24_t oemID = 0;
483 constexpr uint8_t oemAuxillary = 0;
484
485 bool nonNullUsers = 0;
486 uint8_t maxChUsers = 0, enabledUsers = 0, fixedUsers = 0;
487 ipmi::ipmiUserGetAllCounts(maxChUsers, enabledUsers, fixedUsers);
488 nonNullUsers = enabledUsers > 0;
489
490 return ipmi::responseSuccess(
491 channel, rmcpAuthTypes, reserved3, extDataSupport, anonymousLogin,
492 nullUsers, nonNullUsers, userAuth, perMessageAuth, KGStatus, reserved4,
493 rmcp, rmcpp, reserved5, oemID, oemAuxillary);
494}
495
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000496/** @brief implements the set user payload access command.
497 * @param ctx - IPMI context pointer (for channel)
498 * @param channel - channel number (4 bits)
499 * @param reserved1 - skip 4 bits
500 * @param userId - user id (6 bits)
501 * @param operation - access ENABLE /DISABLE. (2 bits)
502 * @param stdPayload0 - IPMI - reserved. (1 bit)
503 * @param stdPayload1 - SOL. (1 bit)
504 * @param stdPayload2 - (1 bit)
505 * @param stdPayload3 - (1 bit)
506 * @param stdPayload4 - (1 bit)
507 * @param stdPayload5 - (1 bit)
508 * @param stdPayload6 - (1 bit)
509 * @param stdPayload7 - (1 bit)
510 * @param stdPayloadEnables2Reserved - (8 bits)
511 * @param oemPayload0 - (1 bit)
512 * @param oemPayload1 - (1 bit)
513 * @param oemPayload2 - (1 bit)
514 * @param oemPayload3 - (1 bit)
515 * @param oemPayload4 - (1 bit)
516 * @param oemPayload5 - (1 bit)
517 * @param oemPayload6 - (1 bit)
518 * @param oemPayload7 - (1 bit)
519 * @param oemPayloadEnables2Reserved - (8 bits)
520 *
521 * @returns IPMI completion code
522 */
523ipmi::RspType<> ipmiSetUserPayloadAccess(
524 ipmi::Context::ptr ctx,
525
526 uint4_t channel, uint4_t reserved,
527
528 uint6_t userId, uint2_t operation,
529
530 bool stdPayload0ipmiReserved, bool stdPayload1SOL, bool stdPayload2,
531 bool stdPayload3, bool stdPayload4, bool stdPayload5, bool stdPayload6,
532 bool stdPayload7,
533
534 uint8_t stdPayloadEnables2Reserved,
535
536 bool oemPayload0, bool oemPayload1, bool oemPayload2, bool oemPayload3,
537 bool oemPayload4, bool oemPayload5, bool oemPayload6, bool oemPayload7,
538
539 uint8_t oemPayloadEnables2Reserved)
540{
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +0000541 auto chNum =
542 convertCurrentChannelNum(static_cast<uint8_t>(channel), ctx->channel);
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000543 // Validate the reserved args. Only SOL payload is supported as on date.
544 if (reserved || stdPayload0ipmiReserved || stdPayload2 || stdPayload3 ||
545 stdPayload4 || stdPayload5 || stdPayload6 || stdPayload7 ||
546 oemPayload0 || oemPayload1 || oemPayload2 || oemPayload3 ||
547 oemPayload4 || oemPayload5 || oemPayload6 || oemPayload7 ||
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +0000548 stdPayloadEnables2Reserved || oemPayloadEnables2Reserved ||
549 !isValidChannel(chNum))
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000550 {
551 return ipmi::responseInvalidFieldRequest();
552 }
553
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +0000554 if ((operation != enableOperation && operation != disableOperation))
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000555 {
556 return ipmi::responseInvalidFieldRequest();
557 }
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +0000558 if (getChannelSessionSupport(chNum) == EChannelSessSupported::none)
559 {
560 return ipmi::response(ccActionNotSupportedForChannel);
561 }
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000562 if (!ipmiUserIsValidUserId(static_cast<uint8_t>(userId)))
563 {
564 return ipmi::responseParmOutOfRange();
565 }
566
567 PayloadAccess payloadAccess = {0};
568 payloadAccess.stdPayloadEnables1[1] = stdPayload1SOL;
569
570 return ipmi::response(ipmiUserSetUserPayloadAccess(
571 chNum, static_cast<uint8_t>(operation), static_cast<uint8_t>(userId),
572 payloadAccess));
573}
574
575/** @brief implements the get user payload access command
576 * This command returns information about user payload enable settings
577 * that were set using the 'Set User Payload Access' Command.
578 *
579 * @param ctx - IPMI context pointer (for channel)
580 * @param channel - channel number
581 * @param reserved1 - skip 4 bits
582 * @param userId - user id
583 * @param reserved2 - skip 2 bits
584 *
585 * @returns IPMI completion code plus response data
586 * - stdPayload0ipmiReserved - IPMI payload (reserved).
587 * - stdPayload1SOL - SOL payload
588 * - stdPayload2
589 * - stdPayload3
590 * - stdPayload4
591 * - stdPayload5
592 * - stdPayload6
593 * - stdPayload7
594
595 * - stdPayloadEnables2Reserved - Reserved.
596
597 * - oemPayload0
598 * - oemPayload1
599 * - oemPayload2
600 * - oemPayload3
601 * - oemPayload4
602 * - oemPayload5
603 * - oemPayload6
604 * - oemPayload7
605
606 * - oemPayloadEnables2Reserved - Reserved
607 */
608ipmi::RspType<bool, // stdPayload0ipmiReserved
609 bool, // stdPayload1SOL
610 bool, // stdPayload2
611 bool, // stdPayload3
612 bool, // stdPayload4
613 bool, // stdPayload5
614 bool, // stdPayload6
615 bool, // stdPayload7
616
617 uint8_t, // stdPayloadEnables2Reserved
618
619 bool, // oemPayload0
620 bool, // oemPayload1
621 bool, // oemPayload2
622 bool, // oemPayload3
623 bool, // oemPayload4
624 bool, // oemPayload5
625 bool, // oemPayload6
626 bool, // oemPayload7
627
628 uint8_t // oemPayloadEnables2Reserved
629 >
630 ipmiGetUserPayloadAccess(ipmi::Context::ptr ctx,
631
632 uint4_t channel, uint4_t reserved1,
633
634 uint6_t userId, uint2_t reserved2)
635{
636 uint8_t chNum =
637 convertCurrentChannelNum(static_cast<uint8_t>(channel), ctx->channel);
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +0000638
639 if (reserved1 || reserved2 || !isValidChannel(chNum))
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000640 {
641 return ipmi::responseInvalidFieldRequest();
642 }
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +0000643 if (getChannelSessionSupport(chNum) == EChannelSessSupported::none)
644 {
645 return ipmi::response(ccActionNotSupportedForChannel);
646 }
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000647 if (!ipmiUserIsValidUserId(static_cast<uint8_t>(userId)))
648 {
649 return ipmi::responseParmOutOfRange();
650 }
651
652 ipmi::Cc retStatus;
653 PayloadAccess payloadAccess = {};
654 retStatus = ipmiUserGetUserPayloadAccess(
655 chNum, static_cast<uint8_t>(userId), payloadAccess);
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000656 if (retStatus != ccSuccess)
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000657 {
658 return ipmi::response(retStatus);
659 }
660 constexpr uint8_t res8bits = 0;
661 return ipmi::responseSuccess(payloadAccess.stdPayloadEnables1.test(0),
662 payloadAccess.stdPayloadEnables1.test(1),
663 payloadAccess.stdPayloadEnables1.test(2),
664 payloadAccess.stdPayloadEnables1.test(3),
665 payloadAccess.stdPayloadEnables1.test(4),
666 payloadAccess.stdPayloadEnables1.test(5),
667 payloadAccess.stdPayloadEnables1.test(6),
668 payloadAccess.stdPayloadEnables1.test(7),
669
670 res8bits,
671
672 payloadAccess.oemPayloadEnables1.test(0),
673 payloadAccess.oemPayloadEnables1.test(1),
674 payloadAccess.oemPayloadEnables1.test(2),
675 payloadAccess.oemPayloadEnables1.test(3),
676 payloadAccess.oemPayloadEnables1.test(4),
677 payloadAccess.oemPayloadEnables1.test(5),
678 payloadAccess.oemPayloadEnables1.test(6),
679 payloadAccess.oemPayloadEnables1.test(7),
680
681 res8bits);
682}
683
William A. Kennington III343d0612018-12-10 15:56:24 -0800684void registerUserIpmiFunctions() __attribute__((constructor));
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530685void registerUserIpmiFunctions()
686{
Richard Marian Thomaiyar0be80bd2020-01-10 12:20:16 +0530687 post_work([]() { ipmiUserInit(); });
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530688 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
689 ipmi::app::cmdSetUserAccessCommand,
690 ipmi::Privilege::Admin, ipmiSetUserAccess);
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530691
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530692 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
693 ipmi::app::cmdGetUserAccessCommand,
694 ipmi::Privilege::Operator, ipmiGetUserAccess);
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530695
Vernon Mauery3c89de12021-08-05 11:08:23 -0700696 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
697 ipmi::app::cmdGetUserNameCommand,
698 ipmi::Privilege::Operator, ipmiGetUserName);
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530699
700 ipmi_register_callback(NETFUN_APP, IPMI_CMD_SET_USER_NAME, NULL,
701 ipmiSetUserName, PRIVILEGE_ADMIN);
702
703 ipmi_register_callback(NETFUN_APP, IPMI_CMD_SET_USER_PASSWORD, NULL,
704 ipmiSetUserPassword, PRIVILEGE_ADMIN);
705
smritic46f6cd2019-03-20 14:09:41 +0530706 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
707 ipmi::app::cmdGetChannelAuthCapabilities,
708 ipmi::Privilege::Callback,
709 ipmiGetChannelAuthenticationCapabilities);
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000710
711 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
712 ipmi::app::cmdSetUserPayloadAccess,
713 ipmi::Privilege::Admin, ipmiSetUserPayloadAccess);
714
715 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
716 ipmi::app::cmdGetUserPayloadAccess,
717 ipmi::Privilege::Operator, ipmiGetUserPayloadAccess);
718
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530719 return;
720}
721} // namespace ipmi