blob: 9a23ac305413c909bc60905f4877a26090db4a3e [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;
Snehalatha Venkatesh37b1d1a2021-06-28 10:13:37 +0000362 if (req->reserved1 || req->reserved2)
363 {
364 log<level::DEBUG>("Invalid data field in request");
365 return ccInvalidFieldRequest;
366 }
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530367
368 // verify input length based on operation. Required password size is 20
369 // bytes as we support only IPMI 2.0, but in order to be compatible with
370 // tools, accept 16 bytes of password size too.
371 if (reqLength < 2 ||
372 // If enable / disable user, reqLength has to be >=2 & <= 22
373 ((req->operation == disableUser || req->operation == enableUser) &&
374 ((reqLength < 2) || (reqLength > sizeof(SetUserPasswordReq)))))
375 {
376 log<level::DEBUG>("Invalid Length");
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000377 return ccReqDataLenInvalid;
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530378 }
379 // If set / test password then password length has to be 16 or 20 bytes
Richard Marian Thomaiyar23df06f2019-01-04 16:42:22 +0530380 // based on the password size bit.
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530381 if (((req->operation == setPassword) || (req->operation == testPassword)) &&
Richard Marian Thomaiyar23df06f2019-01-04 16:42:22 +0530382 (((req->ipmi20 == passwordKeySize20) &&
383 (passwordLength != maxIpmi20PasswordSize)) ||
384 ((req->ipmi20 == passwordKeySize16) &&
385 (passwordLength != maxIpmi15PasswordSize))))
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530386 {
387 log<level::DEBUG>("Invalid Length");
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000388 return ccReqDataLenInvalid;
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530389 }
390
391 std::string userName;
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000392 if (ipmiUserGetUserName(req->userId, userName) != ccSuccess)
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530393 {
394 log<level::DEBUG>("User Name not found",
Ayushi Smriti05ad3412019-10-16 16:10:18 +0530395 entry("USER-ID=%d", (uint8_t)req->userId));
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000396 return ccParmOutOfRange;
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530397 }
398 if (req->operation == setPassword)
399 {
Suryakanth Sekar90b00c72019-01-16 10:37:57 +0530400 return ipmiUserSetUserPassword(
401 req->userId, reinterpret_cast<const char*>(req->userPassword));
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530402 }
Richard Marian Thomaiyar282e79b2018-11-13 19:00:58 +0530403 else if (req->operation == enableUser || req->operation == disableUser)
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530404 {
Richard Marian Thomaiyar282e79b2018-11-13 19:00:58 +0530405 return ipmiUserUpdateEnabledState(req->userId,
406 static_cast<bool>(req->operation));
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530407 }
Richard Marian Thomaiyar282e79b2018-11-13 19:00:58 +0530408 else if (req->operation == testPassword)
409 {
410 auto password = ipmiUserGetPassword(userName);
411 std::string testPassword(
412 reinterpret_cast<const char*>(req->userPassword), 0,
413 passwordLength);
414 // Note: For security reasons password size won't be compared and
415 // wrong password size completion code will not be returned if size
416 // doesn't match as specified in IPMI specification.
417 if (password != testPassword)
418 {
419 log<level::DEBUG>("Test password failed",
Ayushi Smriti05ad3412019-10-16 16:10:18 +0530420 entry("USER-ID=%d", (uint8_t)req->userId));
Jayaprakash Mutyala70bd0632020-10-23 06:24:55 +0000421 // Clear sensitive data
422 OPENSSL_cleanse(&testPassword, testPassword.length());
423 OPENSSL_cleanse(&password, password.length());
424
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000425 return static_cast<Cc>(
Richard Marian Thomaiyar282e79b2018-11-13 19:00:58 +0530426 IPMISetPasswordReturnCodes::ipmiCCPasswdFailMismatch);
427 }
Jayaprakash Mutyala70bd0632020-10-23 06:24:55 +0000428 // Clear sensitive data
429 OPENSSL_cleanse(&testPassword, testPassword.length());
430 OPENSSL_cleanse(&password, password.length());
431
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000432 return ccSuccess;
Richard Marian Thomaiyar282e79b2018-11-13 19:00:58 +0530433 }
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000434 return ccInvalidFieldRequest;
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530435}
436
smritic46f6cd2019-03-20 14:09:41 +0530437/** @brief implements the get channel authentication command
438 * @param ctx - IPMI context pointer (for channel)
439 * @param extData - get IPMI 2.0 extended data
440 * @param reserved1 - skip 3 bits
441 * @param chNum - channel number to get info about
442 * @param reserved2 - skip 4 bits
443 * @param privLevel - requested privilege level
444
445 * @returns ipmi completion code plus response data
446 * - channel number
447 * - rmcpAuthTypes - RMCP auth types (IPMI 1.5)
448 * - reserved1
449 * - extDataSupport - true for IPMI 2.0 extensions
450 * - anonymousLogin - true for anonymous login enabled
451 * - nullUsers - true for null user names enabled
452 * - nonNullUsers - true for non-null usernames enabled
453 * - userAuth - false for user authentication enabled
454 * - perMessageAuth - false for per message authentication enabled
455 * - KGStatus - true for Kg required for authentication
456 * - reserved2
457 * - rmcp - RMCP (IPMI 1.5) connection support
458 * - rmcpp - RMCP+ (IPMI 2.0) connection support
459 * - reserved3
460 * - oemID - OEM IANA of any OEM auth support
461 * - oemAuxillary - OEM data for auth
462 */
463ipmi::RspType<uint8_t, // channel number
464 uint6_t, // rmcpAuthTypes
465 bool, // reserved1
466 bool, // extDataSupport
467 bool, // anonymousLogin
468 bool, // nullUsers
469 bool, // nonNullUsers
470 bool, // userAuth
471 bool, // perMessageAuth
472 bool, // KGStatus
473 uint2_t, // reserved2
474 bool, // rmcp
475 bool, // rmcpp
476 uint6_t, // reserved3
477 uint24_t, // oemID
478 uint8_t // oemAuxillary
479 >
480 ipmiGetChannelAuthenticationCapabilities(ipmi::Context::ptr ctx,
481 uint4_t chNum, uint3_t reserved1,
482 bool extData, uint4_t privLevel,
483 uint4_t reserved2)
484{
smritic46f6cd2019-03-20 14:09:41 +0530485 uint8_t channel =
Vernon Mauery5ed39592019-05-14 09:16:53 -0700486 convertCurrentChannelNum(static_cast<uint8_t>(chNum), ctx->channel);
smritic46f6cd2019-03-20 14:09:41 +0530487
488 if (reserved1 || reserved2 || !isValidChannel(channel) ||
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +0000489 !isValidPrivLimit(static_cast<uint8_t>(privLevel)))
smritic46f6cd2019-03-20 14:09:41 +0530490 {
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +0000491 log<level::DEBUG>(
492 "Get channel auth capabilities - Invalid field in request");
493 return ipmi::responseInvalidFieldRequest();
494 }
495
496 if (getChannelSessionSupport(channel) == EChannelSessSupported::none)
497 {
498 log<level::DEBUG>(
499 "Get channel auth capabilities - No support on channel");
500 return ipmi::response(ccActionNotSupportedForChannel);
smritic46f6cd2019-03-20 14:09:41 +0530501 }
502
503 constexpr bool extDataSupport = true; // true for IPMI 2.0 extensions
504 constexpr bool reserved3 = false;
505 constexpr uint6_t rmcpAuthTypes = 0; // IPMI 1.5 auth types - not supported
506 constexpr uint2_t reserved4 = 0;
507 constexpr bool KGStatus = false; // Not supporting now.
508 constexpr bool perMessageAuth = false; // Per message auth - enabled
509 constexpr bool userAuth = false; // User authentication - enabled
510 constexpr bool nullUsers = false; // Null user names - not supported
511 constexpr bool anonymousLogin = false; // Anonymous login - not supported
512 constexpr uint6_t reserved5 = 0;
513 constexpr bool rmcpp = true; // IPMI 2.0 - supported
514 constexpr bool rmcp = false; // IPMI 1.5 - not supported
515 constexpr uint24_t oemID = 0;
516 constexpr uint8_t oemAuxillary = 0;
517
518 bool nonNullUsers = 0;
519 uint8_t maxChUsers = 0, enabledUsers = 0, fixedUsers = 0;
520 ipmi::ipmiUserGetAllCounts(maxChUsers, enabledUsers, fixedUsers);
521 nonNullUsers = enabledUsers > 0;
522
523 return ipmi::responseSuccess(
524 channel, rmcpAuthTypes, reserved3, extDataSupport, anonymousLogin,
525 nullUsers, nonNullUsers, userAuth, perMessageAuth, KGStatus, reserved4,
526 rmcp, rmcpp, reserved5, oemID, oemAuxillary);
527}
528
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000529/** @brief implements the set user payload access command.
530 * @param ctx - IPMI context pointer (for channel)
531 * @param channel - channel number (4 bits)
532 * @param reserved1 - skip 4 bits
533 * @param userId - user id (6 bits)
534 * @param operation - access ENABLE /DISABLE. (2 bits)
535 * @param stdPayload0 - IPMI - reserved. (1 bit)
536 * @param stdPayload1 - SOL. (1 bit)
537 * @param stdPayload2 - (1 bit)
538 * @param stdPayload3 - (1 bit)
539 * @param stdPayload4 - (1 bit)
540 * @param stdPayload5 - (1 bit)
541 * @param stdPayload6 - (1 bit)
542 * @param stdPayload7 - (1 bit)
543 * @param stdPayloadEnables2Reserved - (8 bits)
544 * @param oemPayload0 - (1 bit)
545 * @param oemPayload1 - (1 bit)
546 * @param oemPayload2 - (1 bit)
547 * @param oemPayload3 - (1 bit)
548 * @param oemPayload4 - (1 bit)
549 * @param oemPayload5 - (1 bit)
550 * @param oemPayload6 - (1 bit)
551 * @param oemPayload7 - (1 bit)
552 * @param oemPayloadEnables2Reserved - (8 bits)
553 *
554 * @returns IPMI completion code
555 */
556ipmi::RspType<> ipmiSetUserPayloadAccess(
557 ipmi::Context::ptr ctx,
558
559 uint4_t channel, uint4_t reserved,
560
561 uint6_t userId, uint2_t operation,
562
563 bool stdPayload0ipmiReserved, bool stdPayload1SOL, bool stdPayload2,
564 bool stdPayload3, bool stdPayload4, bool stdPayload5, bool stdPayload6,
565 bool stdPayload7,
566
567 uint8_t stdPayloadEnables2Reserved,
568
569 bool oemPayload0, bool oemPayload1, bool oemPayload2, bool oemPayload3,
570 bool oemPayload4, bool oemPayload5, bool oemPayload6, bool oemPayload7,
571
572 uint8_t oemPayloadEnables2Reserved)
573{
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +0000574 auto chNum =
575 convertCurrentChannelNum(static_cast<uint8_t>(channel), ctx->channel);
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000576 // Validate the reserved args. Only SOL payload is supported as on date.
577 if (reserved || stdPayload0ipmiReserved || stdPayload2 || stdPayload3 ||
578 stdPayload4 || stdPayload5 || stdPayload6 || stdPayload7 ||
579 oemPayload0 || oemPayload1 || oemPayload2 || oemPayload3 ||
580 oemPayload4 || oemPayload5 || oemPayload6 || oemPayload7 ||
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +0000581 stdPayloadEnables2Reserved || oemPayloadEnables2Reserved ||
582 !isValidChannel(chNum))
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000583 {
584 return ipmi::responseInvalidFieldRequest();
585 }
586
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +0000587 if ((operation != enableOperation && operation != disableOperation))
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000588 {
589 return ipmi::responseInvalidFieldRequest();
590 }
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +0000591 if (getChannelSessionSupport(chNum) == EChannelSessSupported::none)
592 {
593 return ipmi::response(ccActionNotSupportedForChannel);
594 }
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000595 if (!ipmiUserIsValidUserId(static_cast<uint8_t>(userId)))
596 {
597 return ipmi::responseParmOutOfRange();
598 }
599
600 PayloadAccess payloadAccess = {0};
601 payloadAccess.stdPayloadEnables1[1] = stdPayload1SOL;
602
603 return ipmi::response(ipmiUserSetUserPayloadAccess(
604 chNum, static_cast<uint8_t>(operation), static_cast<uint8_t>(userId),
605 payloadAccess));
606}
607
608/** @brief implements the get user payload access command
609 * This command returns information about user payload enable settings
610 * that were set using the 'Set User Payload Access' Command.
611 *
612 * @param ctx - IPMI context pointer (for channel)
613 * @param channel - channel number
614 * @param reserved1 - skip 4 bits
615 * @param userId - user id
616 * @param reserved2 - skip 2 bits
617 *
618 * @returns IPMI completion code plus response data
619 * - stdPayload0ipmiReserved - IPMI payload (reserved).
620 * - stdPayload1SOL - SOL payload
621 * - stdPayload2
622 * - stdPayload3
623 * - stdPayload4
624 * - stdPayload5
625 * - stdPayload6
626 * - stdPayload7
627
628 * - stdPayloadEnables2Reserved - Reserved.
629
630 * - oemPayload0
631 * - oemPayload1
632 * - oemPayload2
633 * - oemPayload3
634 * - oemPayload4
635 * - oemPayload5
636 * - oemPayload6
637 * - oemPayload7
638
639 * - oemPayloadEnables2Reserved - Reserved
640 */
641ipmi::RspType<bool, // stdPayload0ipmiReserved
642 bool, // stdPayload1SOL
643 bool, // stdPayload2
644 bool, // stdPayload3
645 bool, // stdPayload4
646 bool, // stdPayload5
647 bool, // stdPayload6
648 bool, // stdPayload7
649
650 uint8_t, // stdPayloadEnables2Reserved
651
652 bool, // oemPayload0
653 bool, // oemPayload1
654 bool, // oemPayload2
655 bool, // oemPayload3
656 bool, // oemPayload4
657 bool, // oemPayload5
658 bool, // oemPayload6
659 bool, // oemPayload7
660
661 uint8_t // oemPayloadEnables2Reserved
662 >
663 ipmiGetUserPayloadAccess(ipmi::Context::ptr ctx,
664
665 uint4_t channel, uint4_t reserved1,
666
667 uint6_t userId, uint2_t reserved2)
668{
669 uint8_t chNum =
670 convertCurrentChannelNum(static_cast<uint8_t>(channel), ctx->channel);
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +0000671
672 if (reserved1 || reserved2 || !isValidChannel(chNum))
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000673 {
674 return ipmi::responseInvalidFieldRequest();
675 }
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +0000676 if (getChannelSessionSupport(chNum) == EChannelSessSupported::none)
677 {
678 return ipmi::response(ccActionNotSupportedForChannel);
679 }
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000680 if (!ipmiUserIsValidUserId(static_cast<uint8_t>(userId)))
681 {
682 return ipmi::responseParmOutOfRange();
683 }
684
685 ipmi::Cc retStatus;
686 PayloadAccess payloadAccess = {};
687 retStatus = ipmiUserGetUserPayloadAccess(
688 chNum, static_cast<uint8_t>(userId), payloadAccess);
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000689 if (retStatus != ccSuccess)
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000690 {
691 return ipmi::response(retStatus);
692 }
693 constexpr uint8_t res8bits = 0;
694 return ipmi::responseSuccess(payloadAccess.stdPayloadEnables1.test(0),
695 payloadAccess.stdPayloadEnables1.test(1),
696 payloadAccess.stdPayloadEnables1.test(2),
697 payloadAccess.stdPayloadEnables1.test(3),
698 payloadAccess.stdPayloadEnables1.test(4),
699 payloadAccess.stdPayloadEnables1.test(5),
700 payloadAccess.stdPayloadEnables1.test(6),
701 payloadAccess.stdPayloadEnables1.test(7),
702
703 res8bits,
704
705 payloadAccess.oemPayloadEnables1.test(0),
706 payloadAccess.oemPayloadEnables1.test(1),
707 payloadAccess.oemPayloadEnables1.test(2),
708 payloadAccess.oemPayloadEnables1.test(3),
709 payloadAccess.oemPayloadEnables1.test(4),
710 payloadAccess.oemPayloadEnables1.test(5),
711 payloadAccess.oemPayloadEnables1.test(6),
712 payloadAccess.oemPayloadEnables1.test(7),
713
714 res8bits);
715}
716
William A. Kennington III343d0612018-12-10 15:56:24 -0800717void registerUserIpmiFunctions() __attribute__((constructor));
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530718void registerUserIpmiFunctions()
719{
Richard Marian Thomaiyar0be80bd2020-01-10 12:20:16 +0530720 post_work([]() { ipmiUserInit(); });
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530721 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
722 ipmi::app::cmdSetUserAccessCommand,
723 ipmi::Privilege::Admin, ipmiSetUserAccess);
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530724
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530725 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
726 ipmi::app::cmdGetUserAccessCommand,
727 ipmi::Privilege::Operator, ipmiGetUserAccess);
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530728
729 ipmi_register_callback(NETFUN_APP, IPMI_CMD_GET_USER_NAME, NULL,
730 ipmiGetUserName, PRIVILEGE_OPERATOR);
731
732 ipmi_register_callback(NETFUN_APP, IPMI_CMD_SET_USER_NAME, NULL,
733 ipmiSetUserName, PRIVILEGE_ADMIN);
734
735 ipmi_register_callback(NETFUN_APP, IPMI_CMD_SET_USER_PASSWORD, NULL,
736 ipmiSetUserPassword, PRIVILEGE_ADMIN);
737
smritic46f6cd2019-03-20 14:09:41 +0530738 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
739 ipmi::app::cmdGetChannelAuthCapabilities,
740 ipmi::Privilege::Callback,
741 ipmiGetChannelAuthenticationCapabilities);
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000742
743 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
744 ipmi::app::cmdSetUserPayloadAccess,
745 ipmi::Privilege::Admin, ipmiSetUserPayloadAccess);
746
747 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
748 ipmi::app::cmdGetUserPayloadAccess,
749 ipmi::Privilege::Operator, ipmiGetUserPayloadAccess);
750
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530751 return;
752}
753} // namespace ipmi