blob: 3396d2d7425d8416e02aca58d215ae7cddcba9fe [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);
134 uint8_t chNum =
Vernon Mauery5ed39592019-05-14 09:16:53 -0700135 convertCurrentChannelNum(static_cast<uint8_t>(channel), ctx->channel);
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530136 if (reserved1 != 0 || reserved2 != 0 || sessLimit != 0 ||
137 (!isValidChannel(chNum)) ||
138 (!ipmiUserIsValidPrivilege(static_cast<uint8_t>(privilege))) ||
Richard Marian Thomaiyar06df8762018-12-08 17:38:25 +0530139 (EChannelSessSupported::none == getChannelSessionSupport(chNum)))
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530140 {
141 log<level::DEBUG>("Set user access - Invalid field in request");
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530142 return ipmi::responseInvalidFieldRequest();
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530143 }
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530144 if (!ipmiUserIsValidUserId(static_cast<uint8_t>(userId)))
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530145 {
146 log<level::DEBUG>("Set user access - Parameter out of range");
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530147 return ipmi::responseParmOutOfRange();
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530148 }
Richard Marian Thomaiyar06df8762018-12-08 17:38:25 +0530149
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530150 PrivAccess privAccess = {0};
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530151 if (bitsUpdate)
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530152 {
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530153 privAccess.ipmiEnabled = static_cast<uint8_t>(ipmiEnabled);
154 privAccess.linkAuthEnabled = static_cast<uint8_t>(linkAuthEnabled);
155 privAccess.accessCallback = static_cast<uint8_t>(accessCallback);
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530156 }
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530157 privAccess.privilege = static_cast<uint8_t>(privilege);
158 return ipmi::response(
159 ipmiUserSetPrivilegeAccess(static_cast<uint8_t>(userId), chNum,
160 privAccess, static_cast<bool>(bitsUpdate)));
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530161}
162
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530163/** @brief implements the set user access command
164 * @param ctx - IPMI context pointer (for channel)
165 * @param channel - channel number
166 * @param reserved1 - skip 4 bits
167 * @param userId - user id
168 * @param reserved2 - skip 2 bits
169 *
170 * @returns ipmi completion code plus response data
171 * - maxChUsers - max channel users
172 * - reserved1 - skip 2 bits
173 * - enabledUsers - enabled users count
174 * - enabledStatus - enabled status
175 * - fixedUsers - fixed users count
176 * - reserved2 - skip 2 bits
177 * - privilege - user privilege
178 * - ipmiEnabled - ipmi messaging state
179 * - linkAuthEnabled - link authenticatin state
180 * - accessCallback - callback state
181 * - reserved - skip 1 bit
182 */
183ipmi::RspType<uint6_t, // max channel users
184 uint2_t, // reserved1
185
186 uint6_t, // enabled users count
187 uint2_t, // enabled status
188
189 uint6_t, // fixed users count
190 uint2_t, // reserved2
191
192 uint4_t, // privilege
193 uint1_t, // ipmi messaging state
194 uint1_t, // link authentication state
195 uint1_t, // access callback state
196 uint1_t // reserved3
197 >
198 ipmiGetUserAccess(ipmi::Context::ptr ctx, uint4_t channel,
199 uint4_t reserved1,
200
201 uint6_t userId, uint2_t reserved2)
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530202{
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530203 uint8_t chNum =
Vernon Mauery5ed39592019-05-14 09:16:53 -0700204 convertCurrentChannelNum(static_cast<uint8_t>(channel), ctx->channel);
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530205 if (reserved1 != 0 || reserved2 != 0 || (!isValidChannel(chNum)) ||
Richard Marian Thomaiyar06df8762018-12-08 17:38:25 +0530206 (EChannelSessSupported::none == getChannelSessionSupport(chNum)))
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530207 {
208 log<level::DEBUG>("Get user access - Invalid field in request");
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530209 return ipmi::responseInvalidFieldRequest();
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530210 }
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530211 if (!ipmiUserIsValidUserId(static_cast<uint8_t>(userId)))
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530212 {
213 log<level::DEBUG>("Get user access - Parameter out of range");
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530214 return ipmi::responseParmOutOfRange();
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530215 }
216
217 uint8_t maxChUsers = 0, enabledUsers = 0, fixedUsers = 0;
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530218 ipmi::Cc retStatus;
Richard Marian Thomaiyarb6771e02019-01-29 14:42:44 +0530219 retStatus = ipmiUserGetAllCounts(maxChUsers, enabledUsers, fixedUsers);
220 if (retStatus != IPMI_CC_OK)
221 {
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530222 return ipmi::response(retStatus);
Richard Marian Thomaiyarb6771e02019-01-29 14:42:44 +0530223 }
224
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530225 bool enabledState = false;
226 retStatus =
227 ipmiUserCheckEnabled(static_cast<uint8_t>(userId), enabledState);
Richard Marian Thomaiyarb6771e02019-01-29 14:42:44 +0530228 if (retStatus != IPMI_CC_OK)
229 {
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530230 return ipmi::response(retStatus);
Richard Marian Thomaiyarb6771e02019-01-29 14:42:44 +0530231 }
232
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530233 uint2_t enabledStatus = enabledState ? userIdEnabledViaSetPassword
234 : userIdDisabledViaSetPassword;
235 PrivAccess privAccess{};
236 retStatus = ipmiUserGetPrivilegeAccess(static_cast<uint8_t>(userId), chNum,
237 privAccess);
238 if (retStatus != IPMI_CC_OK)
239 {
240 return ipmi::response(retStatus);
241 }
242 constexpr uint2_t res2Bits = 0;
243 return ipmi::responseSuccess(
244 static_cast<uint6_t>(maxChUsers), res2Bits,
245
246 static_cast<uint6_t>(enabledUsers), enabledStatus,
247
248 static_cast<uint6_t>(fixedUsers), res2Bits,
249
250 static_cast<uint4_t>(privAccess.privilege),
251 static_cast<uint1_t>(privAccess.ipmiEnabled),
252 static_cast<uint1_t>(privAccess.linkAuthEnabled),
253 static_cast<uint1_t>(privAccess.accessCallback),
254 static_cast<uint1_t>(privAccess.reserved));
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530255}
256
257ipmi_ret_t ipmiSetUserName(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
258 ipmi_request_t request, ipmi_response_t response,
259 ipmi_data_len_t dataLen, ipmi_context_t context)
260{
261 const SetUserNameReq* req = static_cast<SetUserNameReq*>(request);
262 size_t reqLength = *dataLen;
263 *dataLen = 0;
264
265 if (reqLength != sizeof(*req))
266 {
267 log<level::DEBUG>("Set user name - Invalid Length");
268 return IPMI_CC_REQ_DATA_LEN_INVALID;
269 }
270 if (req->reserved1)
271 {
272 return IPMI_CC_INVALID_FIELD_REQUEST;
273 }
274 if (!ipmiUserIsValidUserId(req->userId))
275 {
276 log<level::DEBUG>("Set user name - Invalid user id");
277 return IPMI_CC_PARM_OUT_OF_RANGE;
278 }
279
280 return ipmiUserSetUserName(req->userId,
281 reinterpret_cast<const char*>(req->userName));
282}
283
284/** @brief implementes the get user name command
285 * @param[in] netfn - specifies netfn.
286 * @param[in] cmd - specifies cmd number.
287 * @param[in] request - pointer to request data.
288 * @param[in, out] dataLen - specifies request data length, and returns
289 * response data length.
290 * @param[in] context - ipmi context.
291 * @returns ipmi completion code.
292 */
293ipmi_ret_t ipmiGetUserName(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
294 ipmi_request_t request, ipmi_response_t response,
295 ipmi_data_len_t dataLen, ipmi_context_t context)
296{
297 const GetUserNameReq* req = static_cast<GetUserNameReq*>(request);
298 size_t reqLength = *dataLen;
299
300 *dataLen = 0;
301
302 if (reqLength != sizeof(*req))
303 {
304 log<level::DEBUG>("Get user name - Invalid Length");
305 return IPMI_CC_REQ_DATA_LEN_INVALID;
306 }
307
308 std::string userName;
309 if (ipmiUserGetUserName(req->userId, userName) != IPMI_CC_OK)
310 { // Invalid User ID
311 log<level::DEBUG>("User Name not found",
Ayushi Smriti05ad3412019-10-16 16:10:18 +0530312 entry("USER-ID=%d", (uint8_t)req->userId));
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530313 return IPMI_CC_PARM_OUT_OF_RANGE;
314 }
315 GetUserNameResp* resp = static_cast<GetUserNameResp*>(response);
316 std::fill(reinterpret_cast<uint8_t*>(resp),
317 reinterpret_cast<uint8_t*>(resp) + sizeof(*resp), 0);
318 userName.copy(reinterpret_cast<char*>(resp->userName),
319 sizeof(resp->userName), 0);
320 *dataLen = sizeof(*resp);
321
322 return IPMI_CC_OK;
323}
324
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530325/** @brief implementes the set user password command
326 * @param[in] netfn - specifies netfn.
327 * @param[in] cmd - specifies cmd number.
328 * @param[in] request - pointer to request data.
329 * @param[in, out] dataLen - specifies request data length, and returns
330 * response data length.
331 * @param[in] context - ipmi context.
332 * @returns ipmi completion code.
333 */
334ipmi_ret_t ipmiSetUserPassword(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
335 ipmi_request_t request, ipmi_response_t response,
336 ipmi_data_len_t dataLen, ipmi_context_t context)
337{
338 const SetUserPasswordReq* req = static_cast<SetUserPasswordReq*>(request);
339 size_t reqLength = *dataLen;
340 // subtract 2 bytes header to know the password length - including NULL
341 uint8_t passwordLength = *dataLen - 2;
342 *dataLen = 0;
343
344 // verify input length based on operation. Required password size is 20
345 // bytes as we support only IPMI 2.0, but in order to be compatible with
346 // tools, accept 16 bytes of password size too.
347 if (reqLength < 2 ||
348 // If enable / disable user, reqLength has to be >=2 & <= 22
349 ((req->operation == disableUser || req->operation == enableUser) &&
350 ((reqLength < 2) || (reqLength > sizeof(SetUserPasswordReq)))))
351 {
352 log<level::DEBUG>("Invalid Length");
353 return IPMI_CC_REQ_DATA_LEN_INVALID;
354 }
355 // If set / test password then password length has to be 16 or 20 bytes
Richard Marian Thomaiyar23df06f2019-01-04 16:42:22 +0530356 // based on the password size bit.
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530357 if (((req->operation == setPassword) || (req->operation == testPassword)) &&
Richard Marian Thomaiyar23df06f2019-01-04 16:42:22 +0530358 (((req->ipmi20 == passwordKeySize20) &&
359 (passwordLength != maxIpmi20PasswordSize)) ||
360 ((req->ipmi20 == passwordKeySize16) &&
361 (passwordLength != maxIpmi15PasswordSize))))
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530362 {
363 log<level::DEBUG>("Invalid Length");
364 return IPMI_CC_REQ_DATA_LEN_INVALID;
365 }
366
367 std::string userName;
368 if (ipmiUserGetUserName(req->userId, userName) != IPMI_CC_OK)
369 {
370 log<level::DEBUG>("User Name not found",
Ayushi Smriti05ad3412019-10-16 16:10:18 +0530371 entry("USER-ID=%d", (uint8_t)req->userId));
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530372 return IPMI_CC_PARM_OUT_OF_RANGE;
373 }
374 if (req->operation == setPassword)
375 {
Suryakanth Sekar90b00c72019-01-16 10:37:57 +0530376 return ipmiUserSetUserPassword(
377 req->userId, reinterpret_cast<const char*>(req->userPassword));
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530378 }
Richard Marian Thomaiyar282e79b2018-11-13 19:00:58 +0530379 else if (req->operation == enableUser || req->operation == disableUser)
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530380 {
Richard Marian Thomaiyar282e79b2018-11-13 19:00:58 +0530381 return ipmiUserUpdateEnabledState(req->userId,
382 static_cast<bool>(req->operation));
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530383 }
Richard Marian Thomaiyar282e79b2018-11-13 19:00:58 +0530384 else if (req->operation == testPassword)
385 {
386 auto password = ipmiUserGetPassword(userName);
387 std::string testPassword(
388 reinterpret_cast<const char*>(req->userPassword), 0,
389 passwordLength);
390 // Note: For security reasons password size won't be compared and
391 // wrong password size completion code will not be returned if size
392 // doesn't match as specified in IPMI specification.
393 if (password != testPassword)
394 {
395 log<level::DEBUG>("Test password failed",
Ayushi Smriti05ad3412019-10-16 16:10:18 +0530396 entry("USER-ID=%d", (uint8_t)req->userId));
Richard Marian Thomaiyar282e79b2018-11-13 19:00:58 +0530397 return static_cast<ipmi_ret_t>(
398 IPMISetPasswordReturnCodes::ipmiCCPasswdFailMismatch);
399 }
400 return IPMI_CC_OK;
401 }
402 return IPMI_CC_INVALID_FIELD_REQUEST;
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530403}
404
smritic46f6cd2019-03-20 14:09:41 +0530405/** @brief implements the get channel authentication command
406 * @param ctx - IPMI context pointer (for channel)
407 * @param extData - get IPMI 2.0 extended data
408 * @param reserved1 - skip 3 bits
409 * @param chNum - channel number to get info about
410 * @param reserved2 - skip 4 bits
411 * @param privLevel - requested privilege level
412
413 * @returns ipmi completion code plus response data
414 * - channel number
415 * - rmcpAuthTypes - RMCP auth types (IPMI 1.5)
416 * - reserved1
417 * - extDataSupport - true for IPMI 2.0 extensions
418 * - anonymousLogin - true for anonymous login enabled
419 * - nullUsers - true for null user names enabled
420 * - nonNullUsers - true for non-null usernames enabled
421 * - userAuth - false for user authentication enabled
422 * - perMessageAuth - false for per message authentication enabled
423 * - KGStatus - true for Kg required for authentication
424 * - reserved2
425 * - rmcp - RMCP (IPMI 1.5) connection support
426 * - rmcpp - RMCP+ (IPMI 2.0) connection support
427 * - reserved3
428 * - oemID - OEM IANA of any OEM auth support
429 * - oemAuxillary - OEM data for auth
430 */
431ipmi::RspType<uint8_t, // channel number
432 uint6_t, // rmcpAuthTypes
433 bool, // reserved1
434 bool, // extDataSupport
435 bool, // anonymousLogin
436 bool, // nullUsers
437 bool, // nonNullUsers
438 bool, // userAuth
439 bool, // perMessageAuth
440 bool, // KGStatus
441 uint2_t, // reserved2
442 bool, // rmcp
443 bool, // rmcpp
444 uint6_t, // reserved3
445 uint24_t, // oemID
446 uint8_t // oemAuxillary
447 >
448 ipmiGetChannelAuthenticationCapabilities(ipmi::Context::ptr ctx,
449 uint4_t chNum, uint3_t reserved1,
450 bool extData, uint4_t privLevel,
451 uint4_t reserved2)
452{
453
454 uint8_t channel =
Vernon Mauery5ed39592019-05-14 09:16:53 -0700455 convertCurrentChannelNum(static_cast<uint8_t>(chNum), ctx->channel);
smritic46f6cd2019-03-20 14:09:41 +0530456
457 if (reserved1 || reserved2 || !isValidChannel(channel) ||
458 !isValidPrivLimit(static_cast<uint8_t>(privLevel)) ||
459 (EChannelSessSupported::none == getChannelSessionSupport(channel)))
460 {
461 return ipmi::response(ccInvalidFieldRequest);
462 }
463
464 constexpr bool extDataSupport = true; // true for IPMI 2.0 extensions
465 constexpr bool reserved3 = false;
466 constexpr uint6_t rmcpAuthTypes = 0; // IPMI 1.5 auth types - not supported
467 constexpr uint2_t reserved4 = 0;
468 constexpr bool KGStatus = false; // Not supporting now.
469 constexpr bool perMessageAuth = false; // Per message auth - enabled
470 constexpr bool userAuth = false; // User authentication - enabled
471 constexpr bool nullUsers = false; // Null user names - not supported
472 constexpr bool anonymousLogin = false; // Anonymous login - not supported
473 constexpr uint6_t reserved5 = 0;
474 constexpr bool rmcpp = true; // IPMI 2.0 - supported
475 constexpr bool rmcp = false; // IPMI 1.5 - not supported
476 constexpr uint24_t oemID = 0;
477 constexpr uint8_t oemAuxillary = 0;
478
479 bool nonNullUsers = 0;
480 uint8_t maxChUsers = 0, enabledUsers = 0, fixedUsers = 0;
481 ipmi::ipmiUserGetAllCounts(maxChUsers, enabledUsers, fixedUsers);
482 nonNullUsers = enabledUsers > 0;
483
484 return ipmi::responseSuccess(
485 channel, rmcpAuthTypes, reserved3, extDataSupport, anonymousLogin,
486 nullUsers, nonNullUsers, userAuth, perMessageAuth, KGStatus, reserved4,
487 rmcp, rmcpp, reserved5, oemID, oemAuxillary);
488}
489
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000490/** @brief implements the set user payload access command.
491 * @param ctx - IPMI context pointer (for channel)
492 * @param channel - channel number (4 bits)
493 * @param reserved1 - skip 4 bits
494 * @param userId - user id (6 bits)
495 * @param operation - access ENABLE /DISABLE. (2 bits)
496 * @param stdPayload0 - IPMI - reserved. (1 bit)
497 * @param stdPayload1 - SOL. (1 bit)
498 * @param stdPayload2 - (1 bit)
499 * @param stdPayload3 - (1 bit)
500 * @param stdPayload4 - (1 bit)
501 * @param stdPayload5 - (1 bit)
502 * @param stdPayload6 - (1 bit)
503 * @param stdPayload7 - (1 bit)
504 * @param stdPayloadEnables2Reserved - (8 bits)
505 * @param oemPayload0 - (1 bit)
506 * @param oemPayload1 - (1 bit)
507 * @param oemPayload2 - (1 bit)
508 * @param oemPayload3 - (1 bit)
509 * @param oemPayload4 - (1 bit)
510 * @param oemPayload5 - (1 bit)
511 * @param oemPayload6 - (1 bit)
512 * @param oemPayload7 - (1 bit)
513 * @param oemPayloadEnables2Reserved - (8 bits)
514 *
515 * @returns IPMI completion code
516 */
517ipmi::RspType<> ipmiSetUserPayloadAccess(
518 ipmi::Context::ptr ctx,
519
520 uint4_t channel, uint4_t reserved,
521
522 uint6_t userId, uint2_t operation,
523
524 bool stdPayload0ipmiReserved, bool stdPayload1SOL, bool stdPayload2,
525 bool stdPayload3, bool stdPayload4, bool stdPayload5, bool stdPayload6,
526 bool stdPayload7,
527
528 uint8_t stdPayloadEnables2Reserved,
529
530 bool oemPayload0, bool oemPayload1, bool oemPayload2, bool oemPayload3,
531 bool oemPayload4, bool oemPayload5, bool oemPayload6, bool oemPayload7,
532
533 uint8_t oemPayloadEnables2Reserved)
534{
535 // Validate the reserved args. Only SOL payload is supported as on date.
536 if (reserved || stdPayload0ipmiReserved || stdPayload2 || stdPayload3 ||
537 stdPayload4 || stdPayload5 || stdPayload6 || stdPayload7 ||
538 oemPayload0 || oemPayload1 || oemPayload2 || oemPayload3 ||
539 oemPayload4 || oemPayload5 || oemPayload6 || oemPayload7 ||
540 stdPayloadEnables2Reserved || oemPayloadEnables2Reserved)
541 {
542 return ipmi::responseInvalidFieldRequest();
543 }
544
545 auto chNum =
546 convertCurrentChannelNum(static_cast<uint8_t>(channel), ctx->channel);
547 if ((operation != enableOperation && operation != disableOperation) ||
548 (!isValidChannel(chNum)) ||
549 (getChannelSessionSupport(chNum) == EChannelSessSupported::none))
550 {
551 return ipmi::responseInvalidFieldRequest();
552 }
553
554 if (!ipmiUserIsValidUserId(static_cast<uint8_t>(userId)))
555 {
556 return ipmi::responseParmOutOfRange();
557 }
558
559 PayloadAccess payloadAccess = {0};
560 payloadAccess.stdPayloadEnables1[1] = stdPayload1SOL;
561
562 return ipmi::response(ipmiUserSetUserPayloadAccess(
563 chNum, static_cast<uint8_t>(operation), static_cast<uint8_t>(userId),
564 payloadAccess));
565}
566
567/** @brief implements the get user payload access command
568 * This command returns information about user payload enable settings
569 * that were set using the 'Set User Payload Access' Command.
570 *
571 * @param ctx - IPMI context pointer (for channel)
572 * @param channel - channel number
573 * @param reserved1 - skip 4 bits
574 * @param userId - user id
575 * @param reserved2 - skip 2 bits
576 *
577 * @returns IPMI completion code plus response data
578 * - stdPayload0ipmiReserved - IPMI payload (reserved).
579 * - stdPayload1SOL - SOL payload
580 * - stdPayload2
581 * - stdPayload3
582 * - stdPayload4
583 * - stdPayload5
584 * - stdPayload6
585 * - stdPayload7
586
587 * - stdPayloadEnables2Reserved - Reserved.
588
589 * - oemPayload0
590 * - oemPayload1
591 * - oemPayload2
592 * - oemPayload3
593 * - oemPayload4
594 * - oemPayload5
595 * - oemPayload6
596 * - oemPayload7
597
598 * - oemPayloadEnables2Reserved - Reserved
599 */
600ipmi::RspType<bool, // stdPayload0ipmiReserved
601 bool, // stdPayload1SOL
602 bool, // stdPayload2
603 bool, // stdPayload3
604 bool, // stdPayload4
605 bool, // stdPayload5
606 bool, // stdPayload6
607 bool, // stdPayload7
608
609 uint8_t, // stdPayloadEnables2Reserved
610
611 bool, // oemPayload0
612 bool, // oemPayload1
613 bool, // oemPayload2
614 bool, // oemPayload3
615 bool, // oemPayload4
616 bool, // oemPayload5
617 bool, // oemPayload6
618 bool, // oemPayload7
619
620 uint8_t // oemPayloadEnables2Reserved
621 >
622 ipmiGetUserPayloadAccess(ipmi::Context::ptr ctx,
623
624 uint4_t channel, uint4_t reserved1,
625
626 uint6_t userId, uint2_t reserved2)
627{
628 uint8_t chNum =
629 convertCurrentChannelNum(static_cast<uint8_t>(channel), ctx->channel);
630 if (reserved1 != 0 || reserved2 != 0 || (!isValidChannel(chNum)) ||
631 (getChannelSessionSupport(chNum) == EChannelSessSupported::none))
632 {
633 return ipmi::responseInvalidFieldRequest();
634 }
635 if (!ipmiUserIsValidUserId(static_cast<uint8_t>(userId)))
636 {
637 return ipmi::responseParmOutOfRange();
638 }
639
640 ipmi::Cc retStatus;
641 PayloadAccess payloadAccess = {};
642 retStatus = ipmiUserGetUserPayloadAccess(
643 chNum, static_cast<uint8_t>(userId), payloadAccess);
644 if (retStatus != IPMI_CC_OK)
645 {
646 return ipmi::response(retStatus);
647 }
648 constexpr uint8_t res8bits = 0;
649 return ipmi::responseSuccess(payloadAccess.stdPayloadEnables1.test(0),
650 payloadAccess.stdPayloadEnables1.test(1),
651 payloadAccess.stdPayloadEnables1.test(2),
652 payloadAccess.stdPayloadEnables1.test(3),
653 payloadAccess.stdPayloadEnables1.test(4),
654 payloadAccess.stdPayloadEnables1.test(5),
655 payloadAccess.stdPayloadEnables1.test(6),
656 payloadAccess.stdPayloadEnables1.test(7),
657
658 res8bits,
659
660 payloadAccess.oemPayloadEnables1.test(0),
661 payloadAccess.oemPayloadEnables1.test(1),
662 payloadAccess.oemPayloadEnables1.test(2),
663 payloadAccess.oemPayloadEnables1.test(3),
664 payloadAccess.oemPayloadEnables1.test(4),
665 payloadAccess.oemPayloadEnables1.test(5),
666 payloadAccess.oemPayloadEnables1.test(6),
667 payloadAccess.oemPayloadEnables1.test(7),
668
669 res8bits);
670}
671
William A. Kennington III343d0612018-12-10 15:56:24 -0800672void registerUserIpmiFunctions() __attribute__((constructor));
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530673void registerUserIpmiFunctions()
674{
Richard Marian Thomaiyar0be80bd2020-01-10 12:20:16 +0530675 post_work([]() { ipmiUserInit(); });
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530676 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
677 ipmi::app::cmdSetUserAccessCommand,
678 ipmi::Privilege::Admin, ipmiSetUserAccess);
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530679
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530680 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
681 ipmi::app::cmdGetUserAccessCommand,
682 ipmi::Privilege::Operator, ipmiGetUserAccess);
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530683
684 ipmi_register_callback(NETFUN_APP, IPMI_CMD_GET_USER_NAME, NULL,
685 ipmiGetUserName, PRIVILEGE_OPERATOR);
686
687 ipmi_register_callback(NETFUN_APP, IPMI_CMD_SET_USER_NAME, NULL,
688 ipmiSetUserName, PRIVILEGE_ADMIN);
689
690 ipmi_register_callback(NETFUN_APP, IPMI_CMD_SET_USER_PASSWORD, NULL,
691 ipmiSetUserPassword, PRIVILEGE_ADMIN);
692
smritic46f6cd2019-03-20 14:09:41 +0530693 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
694 ipmi::app::cmdGetChannelAuthCapabilities,
695 ipmi::Privilege::Callback,
696 ipmiGetChannelAuthenticationCapabilities);
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000697
698 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
699 ipmi::app::cmdSetUserPayloadAccess,
700 ipmi::Privilege::Admin, ipmiSetUserPayloadAccess);
701
702 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
703 ipmi::app::cmdGetUserPayloadAccess,
704 ipmi::Privilege::Operator, ipmiGetUserPayloadAccess);
705
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530706 return;
707}
708} // namespace ipmi