blob: 622857cda8a427493d70b96c1efbf07c5e2ec8ce [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 GetUserNameReq
61 *
62 * Structure for get user name request command (refer spec sec 22.29)
63 */
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +053064struct GetUserNameReq
65{
66#if BYTE_ORDER == LITTLE_ENDIAN
67 uint8_t userId : 6;
68 uint8_t reserved1 : 2;
69#endif
70#if BYTE_ORDER == BIG_ENDIAN
71 uint8_t reserved1 : 2;
72 uint8_t userId : 6;
73#endif
74} __attribute__((packed));
75
Richard Marian Thomaiyar6e1ba9e2018-11-29 06:29:21 +053076/** @struct GetUserNameResp
77 *
78 * Structure for get user name response command (refer spec sec 22.29)
79 */
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +053080struct GetUserNameResp
81{
82 uint8_t userName[16];
83} __attribute__((packed));
84
Richard Marian Thomaiyar6e1ba9e2018-11-29 06:29:21 +053085/** @struct SetUserPasswordReq
86 *
87 * Structure for set user password request command (refer spec sec 22.30)
88 */
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +053089struct SetUserPasswordReq
90{
91#if BYTE_ORDER == LITTLE_ENDIAN
92 uint8_t userId : 6;
93 uint8_t reserved1 : 1;
94 uint8_t ipmi20 : 1;
95 uint8_t operation : 2;
96 uint8_t reserved2 : 6;
97#endif
98#if BYTE_ORDER == BIG_ENDIAN
99 uint8_t ipmi20 : 1;
100 uint8_t reserved1 : 1;
101 uint8_t userId : 6;
102 uint8_t reserved2 : 6;
103 uint8_t operation : 2;
104#endif
105 uint8_t userPassword[maxIpmi20PasswordSize];
106} __attribute__((packed));
107
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530108/** @brief implements the set user access command
109 * @param ctx - IPMI context pointer (for channel)
110 * @param channel - channel number
111 * @param ipmiEnabled - indicates ipmi messaging state
112 * @param linkAuthEnabled - indicates link authentication state
113 * @param accessCallback - indicates callback state
114 * @param bitsUpdate - indicates update request
115 * @param userId - user id
116 * @param reserved1 - skip 2 bits
117 * @param privilege - user privilege
118 * @param reserved2 - skip 4 bits
119 * @param sessionLimit - optional - unused for now
120 *
121 * @returns ipmi completion code
122 */
123ipmi::RspType<> ipmiSetUserAccess(ipmi::Context::ptr ctx, uint4_t channel,
124 uint1_t ipmiEnabled, uint1_t linkAuthEnabled,
125 uint1_t accessCallback, uint1_t bitsUpdate,
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530126
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530127 uint6_t userId, uint2_t reserved1,
128
129 uint4_t privilege, uint4_t reserved2,
130
131 std::optional<uint8_t> sessionLimit)
132{
133 uint8_t sessLimit = sessionLimit.value_or(0);
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +0000134 if (reserved1 || reserved2 || sessLimit ||
135 !ipmiUserIsValidPrivilege(static_cast<uint8_t>(privilege)))
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530136 {
137 log<level::DEBUG>("Set user access - Invalid field in request");
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530138 return ipmi::responseInvalidFieldRequest();
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530139 }
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +0000140
141 uint8_t chNum =
142 convertCurrentChannelNum(static_cast<uint8_t>(channel), ctx->channel);
143 if (!isValidChannel(chNum))
144 {
145 log<level::DEBUG>("Set user access - Invalid channel request");
146 return ipmi::response(invalidChannel);
147 }
148 if (getChannelSessionSupport(chNum) == EChannelSessSupported::none)
149 {
150 log<level::DEBUG>("Set user access - No support on channel");
151 return ipmi::response(ccActionNotSupportedForChannel);
152 }
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530153 if (!ipmiUserIsValidUserId(static_cast<uint8_t>(userId)))
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530154 {
155 log<level::DEBUG>("Set user access - Parameter out of range");
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530156 return ipmi::responseParmOutOfRange();
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530157 }
Richard Marian Thomaiyar06df8762018-12-08 17:38:25 +0530158
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530159 PrivAccess privAccess = {0};
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530160 if (bitsUpdate)
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530161 {
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530162 privAccess.ipmiEnabled = static_cast<uint8_t>(ipmiEnabled);
163 privAccess.linkAuthEnabled = static_cast<uint8_t>(linkAuthEnabled);
164 privAccess.accessCallback = static_cast<uint8_t>(accessCallback);
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530165 }
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530166 privAccess.privilege = static_cast<uint8_t>(privilege);
167 return ipmi::response(
168 ipmiUserSetPrivilegeAccess(static_cast<uint8_t>(userId), chNum,
169 privAccess, static_cast<bool>(bitsUpdate)));
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530170}
171
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530172/** @brief implements the set user access command
173 * @param ctx - IPMI context pointer (for channel)
174 * @param channel - channel number
175 * @param reserved1 - skip 4 bits
176 * @param userId - user id
177 * @param reserved2 - skip 2 bits
178 *
179 * @returns ipmi completion code plus response data
180 * - maxChUsers - max channel users
181 * - reserved1 - skip 2 bits
182 * - enabledUsers - enabled users count
183 * - enabledStatus - enabled status
184 * - fixedUsers - fixed users count
185 * - reserved2 - skip 2 bits
186 * - privilege - user privilege
187 * - ipmiEnabled - ipmi messaging state
188 * - linkAuthEnabled - link authenticatin state
189 * - accessCallback - callback state
190 * - reserved - skip 1 bit
191 */
192ipmi::RspType<uint6_t, // max channel users
193 uint2_t, // reserved1
194
195 uint6_t, // enabled users count
196 uint2_t, // enabled status
197
198 uint6_t, // fixed users count
199 uint2_t, // reserved2
200
201 uint4_t, // privilege
202 uint1_t, // ipmi messaging state
203 uint1_t, // link authentication state
204 uint1_t, // access callback state
205 uint1_t // reserved3
206 >
207 ipmiGetUserAccess(ipmi::Context::ptr ctx, uint4_t channel,
208 uint4_t reserved1,
209
210 uint6_t userId, uint2_t reserved2)
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530211{
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530212 uint8_t chNum =
Vernon Mauery5ed39592019-05-14 09:16:53 -0700213 convertCurrentChannelNum(static_cast<uint8_t>(channel), ctx->channel);
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +0000214
215 if (reserved1 || reserved2 || !isValidChannel(chNum))
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530216 {
217 log<level::DEBUG>("Get user access - Invalid field in request");
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530218 return ipmi::responseInvalidFieldRequest();
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530219 }
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +0000220
221 if (getChannelSessionSupport(chNum) == EChannelSessSupported::none)
222 {
223 log<level::DEBUG>("Get user access - No support on channel");
224 return ipmi::response(ccActionNotSupportedForChannel);
225 }
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530226 if (!ipmiUserIsValidUserId(static_cast<uint8_t>(userId)))
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530227 {
228 log<level::DEBUG>("Get user access - Parameter out of range");
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530229 return ipmi::responseParmOutOfRange();
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530230 }
231
232 uint8_t maxChUsers = 0, enabledUsers = 0, fixedUsers = 0;
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530233 ipmi::Cc retStatus;
Richard Marian Thomaiyarb6771e02019-01-29 14:42:44 +0530234 retStatus = ipmiUserGetAllCounts(maxChUsers, enabledUsers, fixedUsers);
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000235 if (retStatus != ccSuccess)
Richard Marian Thomaiyarb6771e02019-01-29 14:42:44 +0530236 {
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530237 return ipmi::response(retStatus);
Richard Marian Thomaiyarb6771e02019-01-29 14:42:44 +0530238 }
239
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530240 bool enabledState = false;
241 retStatus =
242 ipmiUserCheckEnabled(static_cast<uint8_t>(userId), enabledState);
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000243 if (retStatus != ccSuccess)
Richard Marian Thomaiyarb6771e02019-01-29 14:42:44 +0530244 {
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530245 return ipmi::response(retStatus);
Richard Marian Thomaiyarb6771e02019-01-29 14:42:44 +0530246 }
247
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530248 uint2_t enabledStatus = enabledState ? userIdEnabledViaSetPassword
249 : userIdDisabledViaSetPassword;
250 PrivAccess privAccess{};
251 retStatus = ipmiUserGetPrivilegeAccess(static_cast<uint8_t>(userId), chNum,
252 privAccess);
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000253 if (retStatus != ccSuccess)
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530254 {
255 return ipmi::response(retStatus);
256 }
257 constexpr uint2_t res2Bits = 0;
258 return ipmi::responseSuccess(
259 static_cast<uint6_t>(maxChUsers), res2Bits,
260
261 static_cast<uint6_t>(enabledUsers), enabledStatus,
262
263 static_cast<uint6_t>(fixedUsers), res2Bits,
264
265 static_cast<uint4_t>(privAccess.privilege),
266 static_cast<uint1_t>(privAccess.ipmiEnabled),
267 static_cast<uint1_t>(privAccess.linkAuthEnabled),
268 static_cast<uint1_t>(privAccess.accessCallback),
269 static_cast<uint1_t>(privAccess.reserved));
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530270}
271
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000272Cc ipmiSetUserName(ipmi_netfn_t netfn, ipmi_cmd_t cmd, ipmi_request_t request,
273 ipmi_response_t response, ipmi_data_len_t dataLen,
274 ipmi_context_t context)
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530275{
276 const SetUserNameReq* req = static_cast<SetUserNameReq*>(request);
277 size_t reqLength = *dataLen;
278 *dataLen = 0;
279
280 if (reqLength != sizeof(*req))
281 {
282 log<level::DEBUG>("Set user name - Invalid Length");
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000283 return ccReqDataLenInvalid;
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530284 }
285 if (req->reserved1)
286 {
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000287 return ccInvalidFieldRequest;
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530288 }
289 if (!ipmiUserIsValidUserId(req->userId))
290 {
291 log<level::DEBUG>("Set user name - Invalid user id");
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000292 return ccParmOutOfRange;
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530293 }
294
jayaprakash Mutyalacdcdf2b2020-03-28 00:12:05 +0000295 size_t nameLen = strnlen(reinterpret_cast<const char*>(req->userName),
296 sizeof(req->userName));
297 const std::string strUserName(reinterpret_cast<const char*>(req->userName),
298 nameLen);
299
300 return ipmiUserSetUserName(req->userId, strUserName);
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530301}
302
303/** @brief implementes the get user name command
304 * @param[in] netfn - specifies netfn.
305 * @param[in] cmd - specifies cmd number.
306 * @param[in] request - pointer to request data.
307 * @param[in, out] dataLen - specifies request data length, and returns
308 * response data length.
309 * @param[in] context - ipmi context.
310 * @returns ipmi completion code.
311 */
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000312Cc ipmiGetUserName(ipmi_netfn_t netfn, ipmi_cmd_t cmd, ipmi_request_t request,
313 ipmi_response_t response, ipmi_data_len_t dataLen,
314 ipmi_context_t context)
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530315{
316 const GetUserNameReq* req = static_cast<GetUserNameReq*>(request);
317 size_t reqLength = *dataLen;
318
319 *dataLen = 0;
320
321 if (reqLength != sizeof(*req))
322 {
323 log<level::DEBUG>("Get user name - Invalid Length");
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000324 return ccReqDataLenInvalid;
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530325 }
326
327 std::string userName;
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000328 if (ipmiUserGetUserName(req->userId, userName) != ccSuccess)
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530329 { // Invalid User ID
330 log<level::DEBUG>("User Name not found",
Ayushi Smriti05ad3412019-10-16 16:10:18 +0530331 entry("USER-ID=%d", (uint8_t)req->userId));
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000332 return ccParmOutOfRange;
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530333 }
334 GetUserNameResp* resp = static_cast<GetUserNameResp*>(response);
335 std::fill(reinterpret_cast<uint8_t*>(resp),
336 reinterpret_cast<uint8_t*>(resp) + sizeof(*resp), 0);
337 userName.copy(reinterpret_cast<char*>(resp->userName),
338 sizeof(resp->userName), 0);
339 *dataLen = sizeof(*resp);
340
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000341 return ccSuccess;
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530342}
343
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530344/** @brief implementes the set user password command
345 * @param[in] netfn - specifies netfn.
346 * @param[in] cmd - specifies cmd number.
347 * @param[in] request - pointer to request data.
348 * @param[in, out] dataLen - specifies request data length, and returns
349 * response data length.
350 * @param[in] context - ipmi context.
351 * @returns ipmi completion code.
352 */
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000353Cc ipmiSetUserPassword(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
354 ipmi_request_t request, ipmi_response_t response,
355 ipmi_data_len_t dataLen, ipmi_context_t context)
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530356{
357 const SetUserPasswordReq* req = static_cast<SetUserPasswordReq*>(request);
358 size_t reqLength = *dataLen;
359 // subtract 2 bytes header to know the password length - including NULL
360 uint8_t passwordLength = *dataLen - 2;
361 *dataLen = 0;
362
363 // verify input length based on operation. Required password size is 20
364 // bytes as we support only IPMI 2.0, but in order to be compatible with
365 // tools, accept 16 bytes of password size too.
366 if (reqLength < 2 ||
367 // If enable / disable user, reqLength has to be >=2 & <= 22
368 ((req->operation == disableUser || req->operation == enableUser) &&
369 ((reqLength < 2) || (reqLength > sizeof(SetUserPasswordReq)))))
370 {
371 log<level::DEBUG>("Invalid Length");
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000372 return ccReqDataLenInvalid;
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530373 }
374 // If set / test password then password length has to be 16 or 20 bytes
Richard Marian Thomaiyar23df06f2019-01-04 16:42:22 +0530375 // based on the password size bit.
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530376 if (((req->operation == setPassword) || (req->operation == testPassword)) &&
Richard Marian Thomaiyar23df06f2019-01-04 16:42:22 +0530377 (((req->ipmi20 == passwordKeySize20) &&
378 (passwordLength != maxIpmi20PasswordSize)) ||
379 ((req->ipmi20 == passwordKeySize16) &&
380 (passwordLength != maxIpmi15PasswordSize))))
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530381 {
382 log<level::DEBUG>("Invalid Length");
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000383 return ccReqDataLenInvalid;
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530384 }
385
386 std::string userName;
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000387 if (ipmiUserGetUserName(req->userId, userName) != ccSuccess)
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530388 {
389 log<level::DEBUG>("User Name not found",
Ayushi Smriti05ad3412019-10-16 16:10:18 +0530390 entry("USER-ID=%d", (uint8_t)req->userId));
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000391 return ccParmOutOfRange;
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530392 }
393 if (req->operation == setPassword)
394 {
Suryakanth Sekar90b00c72019-01-16 10:37:57 +0530395 return ipmiUserSetUserPassword(
396 req->userId, reinterpret_cast<const char*>(req->userPassword));
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530397 }
Richard Marian Thomaiyar282e79b2018-11-13 19:00:58 +0530398 else if (req->operation == enableUser || req->operation == disableUser)
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530399 {
Richard Marian Thomaiyar282e79b2018-11-13 19:00:58 +0530400 return ipmiUserUpdateEnabledState(req->userId,
401 static_cast<bool>(req->operation));
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530402 }
Richard Marian Thomaiyar282e79b2018-11-13 19:00:58 +0530403 else if (req->operation == testPassword)
404 {
405 auto password = ipmiUserGetPassword(userName);
406 std::string testPassword(
407 reinterpret_cast<const char*>(req->userPassword), 0,
408 passwordLength);
409 // Note: For security reasons password size won't be compared and
410 // wrong password size completion code will not be returned if size
411 // doesn't match as specified in IPMI specification.
412 if (password != testPassword)
413 {
414 log<level::DEBUG>("Test password failed",
Ayushi Smriti05ad3412019-10-16 16:10:18 +0530415 entry("USER-ID=%d", (uint8_t)req->userId));
Jayaprakash Mutyala70bd0632020-10-23 06:24:55 +0000416 // Clear sensitive data
417 OPENSSL_cleanse(&testPassword, testPassword.length());
418 OPENSSL_cleanse(&password, password.length());
419
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000420 return static_cast<Cc>(
Richard Marian Thomaiyar282e79b2018-11-13 19:00:58 +0530421 IPMISetPasswordReturnCodes::ipmiCCPasswdFailMismatch);
422 }
Jayaprakash Mutyala70bd0632020-10-23 06:24:55 +0000423 // Clear sensitive data
424 OPENSSL_cleanse(&testPassword, testPassword.length());
425 OPENSSL_cleanse(&password, password.length());
426
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000427 return ccSuccess;
Richard Marian Thomaiyar282e79b2018-11-13 19:00:58 +0530428 }
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000429 return ccInvalidFieldRequest;
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530430}
431
smritic46f6cd2019-03-20 14:09:41 +0530432/** @brief implements the get channel authentication command
433 * @param ctx - IPMI context pointer (for channel)
434 * @param extData - get IPMI 2.0 extended data
435 * @param reserved1 - skip 3 bits
436 * @param chNum - channel number to get info about
437 * @param reserved2 - skip 4 bits
438 * @param privLevel - requested privilege level
439
440 * @returns ipmi completion code plus response data
441 * - channel number
442 * - rmcpAuthTypes - RMCP auth types (IPMI 1.5)
443 * - reserved1
444 * - extDataSupport - true for IPMI 2.0 extensions
445 * - anonymousLogin - true for anonymous login enabled
446 * - nullUsers - true for null user names enabled
447 * - nonNullUsers - true for non-null usernames enabled
448 * - userAuth - false for user authentication enabled
449 * - perMessageAuth - false for per message authentication enabled
450 * - KGStatus - true for Kg required for authentication
451 * - reserved2
452 * - rmcp - RMCP (IPMI 1.5) connection support
453 * - rmcpp - RMCP+ (IPMI 2.0) connection support
454 * - reserved3
455 * - oemID - OEM IANA of any OEM auth support
456 * - oemAuxillary - OEM data for auth
457 */
458ipmi::RspType<uint8_t, // channel number
459 uint6_t, // rmcpAuthTypes
460 bool, // reserved1
461 bool, // extDataSupport
462 bool, // anonymousLogin
463 bool, // nullUsers
464 bool, // nonNullUsers
465 bool, // userAuth
466 bool, // perMessageAuth
467 bool, // KGStatus
468 uint2_t, // reserved2
469 bool, // rmcp
470 bool, // rmcpp
471 uint6_t, // reserved3
472 uint24_t, // oemID
473 uint8_t // oemAuxillary
474 >
475 ipmiGetChannelAuthenticationCapabilities(ipmi::Context::ptr ctx,
476 uint4_t chNum, uint3_t reserved1,
477 bool extData, uint4_t privLevel,
478 uint4_t reserved2)
479{
smritic46f6cd2019-03-20 14:09:41 +0530480 uint8_t channel =
Vernon Mauery5ed39592019-05-14 09:16:53 -0700481 convertCurrentChannelNum(static_cast<uint8_t>(chNum), ctx->channel);
smritic46f6cd2019-03-20 14:09:41 +0530482
483 if (reserved1 || reserved2 || !isValidChannel(channel) ||
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +0000484 !isValidPrivLimit(static_cast<uint8_t>(privLevel)))
smritic46f6cd2019-03-20 14:09:41 +0530485 {
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +0000486 log<level::DEBUG>(
487 "Get channel auth capabilities - Invalid field in request");
488 return ipmi::responseInvalidFieldRequest();
489 }
490
491 if (getChannelSessionSupport(channel) == EChannelSessSupported::none)
492 {
493 log<level::DEBUG>(
494 "Get channel auth capabilities - No support on channel");
495 return ipmi::response(ccActionNotSupportedForChannel);
smritic46f6cd2019-03-20 14:09:41 +0530496 }
497
498 constexpr bool extDataSupport = true; // true for IPMI 2.0 extensions
499 constexpr bool reserved3 = false;
500 constexpr uint6_t rmcpAuthTypes = 0; // IPMI 1.5 auth types - not supported
501 constexpr uint2_t reserved4 = 0;
502 constexpr bool KGStatus = false; // Not supporting now.
503 constexpr bool perMessageAuth = false; // Per message auth - enabled
504 constexpr bool userAuth = false; // User authentication - enabled
505 constexpr bool nullUsers = false; // Null user names - not supported
506 constexpr bool anonymousLogin = false; // Anonymous login - not supported
507 constexpr uint6_t reserved5 = 0;
508 constexpr bool rmcpp = true; // IPMI 2.0 - supported
509 constexpr bool rmcp = false; // IPMI 1.5 - not supported
510 constexpr uint24_t oemID = 0;
511 constexpr uint8_t oemAuxillary = 0;
512
513 bool nonNullUsers = 0;
514 uint8_t maxChUsers = 0, enabledUsers = 0, fixedUsers = 0;
515 ipmi::ipmiUserGetAllCounts(maxChUsers, enabledUsers, fixedUsers);
516 nonNullUsers = enabledUsers > 0;
517
518 return ipmi::responseSuccess(
519 channel, rmcpAuthTypes, reserved3, extDataSupport, anonymousLogin,
520 nullUsers, nonNullUsers, userAuth, perMessageAuth, KGStatus, reserved4,
521 rmcp, rmcpp, reserved5, oemID, oemAuxillary);
522}
523
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000524/** @brief implements the set user payload access command.
525 * @param ctx - IPMI context pointer (for channel)
526 * @param channel - channel number (4 bits)
527 * @param reserved1 - skip 4 bits
528 * @param userId - user id (6 bits)
529 * @param operation - access ENABLE /DISABLE. (2 bits)
530 * @param stdPayload0 - IPMI - reserved. (1 bit)
531 * @param stdPayload1 - SOL. (1 bit)
532 * @param stdPayload2 - (1 bit)
533 * @param stdPayload3 - (1 bit)
534 * @param stdPayload4 - (1 bit)
535 * @param stdPayload5 - (1 bit)
536 * @param stdPayload6 - (1 bit)
537 * @param stdPayload7 - (1 bit)
538 * @param stdPayloadEnables2Reserved - (8 bits)
539 * @param oemPayload0 - (1 bit)
540 * @param oemPayload1 - (1 bit)
541 * @param oemPayload2 - (1 bit)
542 * @param oemPayload3 - (1 bit)
543 * @param oemPayload4 - (1 bit)
544 * @param oemPayload5 - (1 bit)
545 * @param oemPayload6 - (1 bit)
546 * @param oemPayload7 - (1 bit)
547 * @param oemPayloadEnables2Reserved - (8 bits)
548 *
549 * @returns IPMI completion code
550 */
551ipmi::RspType<> ipmiSetUserPayloadAccess(
552 ipmi::Context::ptr ctx,
553
554 uint4_t channel, uint4_t reserved,
555
556 uint6_t userId, uint2_t operation,
557
558 bool stdPayload0ipmiReserved, bool stdPayload1SOL, bool stdPayload2,
559 bool stdPayload3, bool stdPayload4, bool stdPayload5, bool stdPayload6,
560 bool stdPayload7,
561
562 uint8_t stdPayloadEnables2Reserved,
563
564 bool oemPayload0, bool oemPayload1, bool oemPayload2, bool oemPayload3,
565 bool oemPayload4, bool oemPayload5, bool oemPayload6, bool oemPayload7,
566
567 uint8_t oemPayloadEnables2Reserved)
568{
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +0000569 auto chNum =
570 convertCurrentChannelNum(static_cast<uint8_t>(channel), ctx->channel);
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000571 // Validate the reserved args. Only SOL payload is supported as on date.
572 if (reserved || stdPayload0ipmiReserved || stdPayload2 || stdPayload3 ||
573 stdPayload4 || stdPayload5 || stdPayload6 || stdPayload7 ||
574 oemPayload0 || oemPayload1 || oemPayload2 || oemPayload3 ||
575 oemPayload4 || oemPayload5 || oemPayload6 || oemPayload7 ||
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +0000576 stdPayloadEnables2Reserved || oemPayloadEnables2Reserved ||
577 !isValidChannel(chNum))
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000578 {
579 return ipmi::responseInvalidFieldRequest();
580 }
581
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +0000582 if ((operation != enableOperation && operation != disableOperation))
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000583 {
584 return ipmi::responseInvalidFieldRequest();
585 }
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +0000586 if (getChannelSessionSupport(chNum) == EChannelSessSupported::none)
587 {
588 return ipmi::response(ccActionNotSupportedForChannel);
589 }
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000590 if (!ipmiUserIsValidUserId(static_cast<uint8_t>(userId)))
591 {
592 return ipmi::responseParmOutOfRange();
593 }
594
595 PayloadAccess payloadAccess = {0};
596 payloadAccess.stdPayloadEnables1[1] = stdPayload1SOL;
597
598 return ipmi::response(ipmiUserSetUserPayloadAccess(
599 chNum, static_cast<uint8_t>(operation), static_cast<uint8_t>(userId),
600 payloadAccess));
601}
602
603/** @brief implements the get user payload access command
604 * This command returns information about user payload enable settings
605 * that were set using the 'Set User Payload Access' Command.
606 *
607 * @param ctx - IPMI context pointer (for channel)
608 * @param channel - channel number
609 * @param reserved1 - skip 4 bits
610 * @param userId - user id
611 * @param reserved2 - skip 2 bits
612 *
613 * @returns IPMI completion code plus response data
614 * - stdPayload0ipmiReserved - IPMI payload (reserved).
615 * - stdPayload1SOL - SOL payload
616 * - stdPayload2
617 * - stdPayload3
618 * - stdPayload4
619 * - stdPayload5
620 * - stdPayload6
621 * - stdPayload7
622
623 * - stdPayloadEnables2Reserved - Reserved.
624
625 * - oemPayload0
626 * - oemPayload1
627 * - oemPayload2
628 * - oemPayload3
629 * - oemPayload4
630 * - oemPayload5
631 * - oemPayload6
632 * - oemPayload7
633
634 * - oemPayloadEnables2Reserved - Reserved
635 */
636ipmi::RspType<bool, // stdPayload0ipmiReserved
637 bool, // stdPayload1SOL
638 bool, // stdPayload2
639 bool, // stdPayload3
640 bool, // stdPayload4
641 bool, // stdPayload5
642 bool, // stdPayload6
643 bool, // stdPayload7
644
645 uint8_t, // stdPayloadEnables2Reserved
646
647 bool, // oemPayload0
648 bool, // oemPayload1
649 bool, // oemPayload2
650 bool, // oemPayload3
651 bool, // oemPayload4
652 bool, // oemPayload5
653 bool, // oemPayload6
654 bool, // oemPayload7
655
656 uint8_t // oemPayloadEnables2Reserved
657 >
658 ipmiGetUserPayloadAccess(ipmi::Context::ptr ctx,
659
660 uint4_t channel, uint4_t reserved1,
661
662 uint6_t userId, uint2_t reserved2)
663{
664 uint8_t chNum =
665 convertCurrentChannelNum(static_cast<uint8_t>(channel), ctx->channel);
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +0000666
667 if (reserved1 || reserved2 || !isValidChannel(chNum))
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000668 {
669 return ipmi::responseInvalidFieldRequest();
670 }
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +0000671 if (getChannelSessionSupport(chNum) == EChannelSessSupported::none)
672 {
673 return ipmi::response(ccActionNotSupportedForChannel);
674 }
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000675 if (!ipmiUserIsValidUserId(static_cast<uint8_t>(userId)))
676 {
677 return ipmi::responseParmOutOfRange();
678 }
679
680 ipmi::Cc retStatus;
681 PayloadAccess payloadAccess = {};
682 retStatus = ipmiUserGetUserPayloadAccess(
683 chNum, static_cast<uint8_t>(userId), payloadAccess);
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000684 if (retStatus != ccSuccess)
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000685 {
686 return ipmi::response(retStatus);
687 }
688 constexpr uint8_t res8bits = 0;
689 return ipmi::responseSuccess(payloadAccess.stdPayloadEnables1.test(0),
690 payloadAccess.stdPayloadEnables1.test(1),
691 payloadAccess.stdPayloadEnables1.test(2),
692 payloadAccess.stdPayloadEnables1.test(3),
693 payloadAccess.stdPayloadEnables1.test(4),
694 payloadAccess.stdPayloadEnables1.test(5),
695 payloadAccess.stdPayloadEnables1.test(6),
696 payloadAccess.stdPayloadEnables1.test(7),
697
698 res8bits,
699
700 payloadAccess.oemPayloadEnables1.test(0),
701 payloadAccess.oemPayloadEnables1.test(1),
702 payloadAccess.oemPayloadEnables1.test(2),
703 payloadAccess.oemPayloadEnables1.test(3),
704 payloadAccess.oemPayloadEnables1.test(4),
705 payloadAccess.oemPayloadEnables1.test(5),
706 payloadAccess.oemPayloadEnables1.test(6),
707 payloadAccess.oemPayloadEnables1.test(7),
708
709 res8bits);
710}
711
William A. Kennington III343d0612018-12-10 15:56:24 -0800712void registerUserIpmiFunctions() __attribute__((constructor));
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530713void registerUserIpmiFunctions()
714{
Richard Marian Thomaiyar0be80bd2020-01-10 12:20:16 +0530715 post_work([]() { ipmiUserInit(); });
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530716 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
717 ipmi::app::cmdSetUserAccessCommand,
718 ipmi::Privilege::Admin, ipmiSetUserAccess);
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530719
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530720 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
721 ipmi::app::cmdGetUserAccessCommand,
722 ipmi::Privilege::Operator, ipmiGetUserAccess);
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530723
724 ipmi_register_callback(NETFUN_APP, IPMI_CMD_GET_USER_NAME, NULL,
725 ipmiGetUserName, PRIVILEGE_OPERATOR);
726
727 ipmi_register_callback(NETFUN_APP, IPMI_CMD_SET_USER_NAME, NULL,
728 ipmiSetUserName, PRIVILEGE_ADMIN);
729
730 ipmi_register_callback(NETFUN_APP, IPMI_CMD_SET_USER_PASSWORD, NULL,
731 ipmiSetUserPassword, PRIVILEGE_ADMIN);
732
smritic46f6cd2019-03-20 14:09:41 +0530733 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
734 ipmi::app::cmdGetChannelAuthCapabilities,
735 ipmi::Privilege::Callback,
736 ipmiGetChannelAuthenticationCapabilities);
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000737
738 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
739 ipmi::app::cmdSetUserPayloadAccess,
740 ipmi::Privilege::Admin, ipmiSetUserPayloadAccess);
741
742 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
743 ipmi::app::cmdGetUserPayloadAccess,
744 ipmi::Privilege::Operator, ipmiGetUserPayloadAccess);
745
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530746 return;
747}
748} // namespace ipmi