blob: bda40279fa0b127088e50779393030010318a8e8 [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));
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000416 return static_cast<Cc>(
Richard Marian Thomaiyar282e79b2018-11-13 19:00:58 +0530417 IPMISetPasswordReturnCodes::ipmiCCPasswdFailMismatch);
418 }
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000419 return ccSuccess;
Richard Marian Thomaiyar282e79b2018-11-13 19:00:58 +0530420 }
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000421 return ccInvalidFieldRequest;
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530422}
423
smritic46f6cd2019-03-20 14:09:41 +0530424/** @brief implements the get channel authentication command
425 * @param ctx - IPMI context pointer (for channel)
426 * @param extData - get IPMI 2.0 extended data
427 * @param reserved1 - skip 3 bits
428 * @param chNum - channel number to get info about
429 * @param reserved2 - skip 4 bits
430 * @param privLevel - requested privilege level
431
432 * @returns ipmi completion code plus response data
433 * - channel number
434 * - rmcpAuthTypes - RMCP auth types (IPMI 1.5)
435 * - reserved1
436 * - extDataSupport - true for IPMI 2.0 extensions
437 * - anonymousLogin - true for anonymous login enabled
438 * - nullUsers - true for null user names enabled
439 * - nonNullUsers - true for non-null usernames enabled
440 * - userAuth - false for user authentication enabled
441 * - perMessageAuth - false for per message authentication enabled
442 * - KGStatus - true for Kg required for authentication
443 * - reserved2
444 * - rmcp - RMCP (IPMI 1.5) connection support
445 * - rmcpp - RMCP+ (IPMI 2.0) connection support
446 * - reserved3
447 * - oemID - OEM IANA of any OEM auth support
448 * - oemAuxillary - OEM data for auth
449 */
450ipmi::RspType<uint8_t, // channel number
451 uint6_t, // rmcpAuthTypes
452 bool, // reserved1
453 bool, // extDataSupport
454 bool, // anonymousLogin
455 bool, // nullUsers
456 bool, // nonNullUsers
457 bool, // userAuth
458 bool, // perMessageAuth
459 bool, // KGStatus
460 uint2_t, // reserved2
461 bool, // rmcp
462 bool, // rmcpp
463 uint6_t, // reserved3
464 uint24_t, // oemID
465 uint8_t // oemAuxillary
466 >
467 ipmiGetChannelAuthenticationCapabilities(ipmi::Context::ptr ctx,
468 uint4_t chNum, uint3_t reserved1,
469 bool extData, uint4_t privLevel,
470 uint4_t reserved2)
471{
smritic46f6cd2019-03-20 14:09:41 +0530472 uint8_t channel =
Vernon Mauery5ed39592019-05-14 09:16:53 -0700473 convertCurrentChannelNum(static_cast<uint8_t>(chNum), ctx->channel);
smritic46f6cd2019-03-20 14:09:41 +0530474
475 if (reserved1 || reserved2 || !isValidChannel(channel) ||
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +0000476 !isValidPrivLimit(static_cast<uint8_t>(privLevel)))
smritic46f6cd2019-03-20 14:09:41 +0530477 {
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +0000478 log<level::DEBUG>(
479 "Get channel auth capabilities - Invalid field in request");
480 return ipmi::responseInvalidFieldRequest();
481 }
482
483 if (getChannelSessionSupport(channel) == EChannelSessSupported::none)
484 {
485 log<level::DEBUG>(
486 "Get channel auth capabilities - No support on channel");
487 return ipmi::response(ccActionNotSupportedForChannel);
smritic46f6cd2019-03-20 14:09:41 +0530488 }
489
490 constexpr bool extDataSupport = true; // true for IPMI 2.0 extensions
491 constexpr bool reserved3 = false;
492 constexpr uint6_t rmcpAuthTypes = 0; // IPMI 1.5 auth types - not supported
493 constexpr uint2_t reserved4 = 0;
494 constexpr bool KGStatus = false; // Not supporting now.
495 constexpr bool perMessageAuth = false; // Per message auth - enabled
496 constexpr bool userAuth = false; // User authentication - enabled
497 constexpr bool nullUsers = false; // Null user names - not supported
498 constexpr bool anonymousLogin = false; // Anonymous login - not supported
499 constexpr uint6_t reserved5 = 0;
500 constexpr bool rmcpp = true; // IPMI 2.0 - supported
501 constexpr bool rmcp = false; // IPMI 1.5 - not supported
502 constexpr uint24_t oemID = 0;
503 constexpr uint8_t oemAuxillary = 0;
504
505 bool nonNullUsers = 0;
506 uint8_t maxChUsers = 0, enabledUsers = 0, fixedUsers = 0;
507 ipmi::ipmiUserGetAllCounts(maxChUsers, enabledUsers, fixedUsers);
508 nonNullUsers = enabledUsers > 0;
509
510 return ipmi::responseSuccess(
511 channel, rmcpAuthTypes, reserved3, extDataSupport, anonymousLogin,
512 nullUsers, nonNullUsers, userAuth, perMessageAuth, KGStatus, reserved4,
513 rmcp, rmcpp, reserved5, oemID, oemAuxillary);
514}
515
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000516/** @brief implements the set user payload access command.
517 * @param ctx - IPMI context pointer (for channel)
518 * @param channel - channel number (4 bits)
519 * @param reserved1 - skip 4 bits
520 * @param userId - user id (6 bits)
521 * @param operation - access ENABLE /DISABLE. (2 bits)
522 * @param stdPayload0 - IPMI - reserved. (1 bit)
523 * @param stdPayload1 - SOL. (1 bit)
524 * @param stdPayload2 - (1 bit)
525 * @param stdPayload3 - (1 bit)
526 * @param stdPayload4 - (1 bit)
527 * @param stdPayload5 - (1 bit)
528 * @param stdPayload6 - (1 bit)
529 * @param stdPayload7 - (1 bit)
530 * @param stdPayloadEnables2Reserved - (8 bits)
531 * @param oemPayload0 - (1 bit)
532 * @param oemPayload1 - (1 bit)
533 * @param oemPayload2 - (1 bit)
534 * @param oemPayload3 - (1 bit)
535 * @param oemPayload4 - (1 bit)
536 * @param oemPayload5 - (1 bit)
537 * @param oemPayload6 - (1 bit)
538 * @param oemPayload7 - (1 bit)
539 * @param oemPayloadEnables2Reserved - (8 bits)
540 *
541 * @returns IPMI completion code
542 */
543ipmi::RspType<> ipmiSetUserPayloadAccess(
544 ipmi::Context::ptr ctx,
545
546 uint4_t channel, uint4_t reserved,
547
548 uint6_t userId, uint2_t operation,
549
550 bool stdPayload0ipmiReserved, bool stdPayload1SOL, bool stdPayload2,
551 bool stdPayload3, bool stdPayload4, bool stdPayload5, bool stdPayload6,
552 bool stdPayload7,
553
554 uint8_t stdPayloadEnables2Reserved,
555
556 bool oemPayload0, bool oemPayload1, bool oemPayload2, bool oemPayload3,
557 bool oemPayload4, bool oemPayload5, bool oemPayload6, bool oemPayload7,
558
559 uint8_t oemPayloadEnables2Reserved)
560{
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +0000561 auto chNum =
562 convertCurrentChannelNum(static_cast<uint8_t>(channel), ctx->channel);
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000563 // Validate the reserved args. Only SOL payload is supported as on date.
564 if (reserved || stdPayload0ipmiReserved || stdPayload2 || stdPayload3 ||
565 stdPayload4 || stdPayload5 || stdPayload6 || stdPayload7 ||
566 oemPayload0 || oemPayload1 || oemPayload2 || oemPayload3 ||
567 oemPayload4 || oemPayload5 || oemPayload6 || oemPayload7 ||
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +0000568 stdPayloadEnables2Reserved || oemPayloadEnables2Reserved ||
569 !isValidChannel(chNum))
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000570 {
571 return ipmi::responseInvalidFieldRequest();
572 }
573
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +0000574 if ((operation != enableOperation && operation != disableOperation))
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000575 {
576 return ipmi::responseInvalidFieldRequest();
577 }
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +0000578 if (getChannelSessionSupport(chNum) == EChannelSessSupported::none)
579 {
580 return ipmi::response(ccActionNotSupportedForChannel);
581 }
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000582 if (!ipmiUserIsValidUserId(static_cast<uint8_t>(userId)))
583 {
584 return ipmi::responseParmOutOfRange();
585 }
586
587 PayloadAccess payloadAccess = {0};
588 payloadAccess.stdPayloadEnables1[1] = stdPayload1SOL;
589
590 return ipmi::response(ipmiUserSetUserPayloadAccess(
591 chNum, static_cast<uint8_t>(operation), static_cast<uint8_t>(userId),
592 payloadAccess));
593}
594
595/** @brief implements the get user payload access command
596 * This command returns information about user payload enable settings
597 * that were set using the 'Set User Payload Access' Command.
598 *
599 * @param ctx - IPMI context pointer (for channel)
600 * @param channel - channel number
601 * @param reserved1 - skip 4 bits
602 * @param userId - user id
603 * @param reserved2 - skip 2 bits
604 *
605 * @returns IPMI completion code plus response data
606 * - stdPayload0ipmiReserved - IPMI payload (reserved).
607 * - stdPayload1SOL - SOL payload
608 * - stdPayload2
609 * - stdPayload3
610 * - stdPayload4
611 * - stdPayload5
612 * - stdPayload6
613 * - stdPayload7
614
615 * - stdPayloadEnables2Reserved - Reserved.
616
617 * - oemPayload0
618 * - oemPayload1
619 * - oemPayload2
620 * - oemPayload3
621 * - oemPayload4
622 * - oemPayload5
623 * - oemPayload6
624 * - oemPayload7
625
626 * - oemPayloadEnables2Reserved - Reserved
627 */
628ipmi::RspType<bool, // stdPayload0ipmiReserved
629 bool, // stdPayload1SOL
630 bool, // stdPayload2
631 bool, // stdPayload3
632 bool, // stdPayload4
633 bool, // stdPayload5
634 bool, // stdPayload6
635 bool, // stdPayload7
636
637 uint8_t, // stdPayloadEnables2Reserved
638
639 bool, // oemPayload0
640 bool, // oemPayload1
641 bool, // oemPayload2
642 bool, // oemPayload3
643 bool, // oemPayload4
644 bool, // oemPayload5
645 bool, // oemPayload6
646 bool, // oemPayload7
647
648 uint8_t // oemPayloadEnables2Reserved
649 >
650 ipmiGetUserPayloadAccess(ipmi::Context::ptr ctx,
651
652 uint4_t channel, uint4_t reserved1,
653
654 uint6_t userId, uint2_t reserved2)
655{
656 uint8_t chNum =
657 convertCurrentChannelNum(static_cast<uint8_t>(channel), ctx->channel);
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +0000658
659 if (reserved1 || reserved2 || !isValidChannel(chNum))
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000660 {
661 return ipmi::responseInvalidFieldRequest();
662 }
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +0000663 if (getChannelSessionSupport(chNum) == EChannelSessSupported::none)
664 {
665 return ipmi::response(ccActionNotSupportedForChannel);
666 }
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000667 if (!ipmiUserIsValidUserId(static_cast<uint8_t>(userId)))
668 {
669 return ipmi::responseParmOutOfRange();
670 }
671
672 ipmi::Cc retStatus;
673 PayloadAccess payloadAccess = {};
674 retStatus = ipmiUserGetUserPayloadAccess(
675 chNum, static_cast<uint8_t>(userId), payloadAccess);
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000676 if (retStatus != ccSuccess)
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000677 {
678 return ipmi::response(retStatus);
679 }
680 constexpr uint8_t res8bits = 0;
681 return ipmi::responseSuccess(payloadAccess.stdPayloadEnables1.test(0),
682 payloadAccess.stdPayloadEnables1.test(1),
683 payloadAccess.stdPayloadEnables1.test(2),
684 payloadAccess.stdPayloadEnables1.test(3),
685 payloadAccess.stdPayloadEnables1.test(4),
686 payloadAccess.stdPayloadEnables1.test(5),
687 payloadAccess.stdPayloadEnables1.test(6),
688 payloadAccess.stdPayloadEnables1.test(7),
689
690 res8bits,
691
692 payloadAccess.oemPayloadEnables1.test(0),
693 payloadAccess.oemPayloadEnables1.test(1),
694 payloadAccess.oemPayloadEnables1.test(2),
695 payloadAccess.oemPayloadEnables1.test(3),
696 payloadAccess.oemPayloadEnables1.test(4),
697 payloadAccess.oemPayloadEnables1.test(5),
698 payloadAccess.oemPayloadEnables1.test(6),
699 payloadAccess.oemPayloadEnables1.test(7),
700
701 res8bits);
702}
703
William A. Kennington III343d0612018-12-10 15:56:24 -0800704void registerUserIpmiFunctions() __attribute__((constructor));
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530705void registerUserIpmiFunctions()
706{
Richard Marian Thomaiyar0be80bd2020-01-10 12:20:16 +0530707 post_work([]() { ipmiUserInit(); });
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530708 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
709 ipmi::app::cmdSetUserAccessCommand,
710 ipmi::Privilege::Admin, ipmiSetUserAccess);
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530711
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530712 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
713 ipmi::app::cmdGetUserAccessCommand,
714 ipmi::Privilege::Operator, ipmiGetUserAccess);
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530715
716 ipmi_register_callback(NETFUN_APP, IPMI_CMD_GET_USER_NAME, NULL,
717 ipmiGetUserName, PRIVILEGE_OPERATOR);
718
719 ipmi_register_callback(NETFUN_APP, IPMI_CMD_SET_USER_NAME, NULL,
720 ipmiSetUserName, PRIVILEGE_ADMIN);
721
722 ipmi_register_callback(NETFUN_APP, IPMI_CMD_SET_USER_PASSWORD, NULL,
723 ipmiSetUserPassword, PRIVILEGE_ADMIN);
724
smritic46f6cd2019-03-20 14:09:41 +0530725 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
726 ipmi::app::cmdGetChannelAuthCapabilities,
727 ipmi::Privilege::Callback,
728 ipmiGetChannelAuthenticationCapabilities);
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000729
730 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
731 ipmi::app::cmdSetUserPayloadAccess,
732 ipmi::Privilege::Admin, ipmiSetUserPayloadAccess);
733
734 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
735 ipmi::app::cmdGetUserPayloadAccess,
736 ipmi::Privilege::Operator, ipmiGetUserPayloadAccess);
737
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530738 return;
739}
740} // namespace ipmi