blob: c48c476505cc3c0f59831b5bad4b2e1d3dada925 [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 SetUserPasswordReq
44 *
45 * Structure for set user password request command (refer spec sec 22.30)
46 */
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +053047struct SetUserPasswordReq
48{
49#if BYTE_ORDER == LITTLE_ENDIAN
50 uint8_t userId : 6;
51 uint8_t reserved1 : 1;
52 uint8_t ipmi20 : 1;
53 uint8_t operation : 2;
54 uint8_t reserved2 : 6;
55#endif
56#if BYTE_ORDER == BIG_ENDIAN
57 uint8_t ipmi20 : 1;
58 uint8_t reserved1 : 1;
59 uint8_t userId : 6;
60 uint8_t reserved2 : 6;
61 uint8_t operation : 2;
62#endif
63 uint8_t userPassword[maxIpmi20PasswordSize];
64} __attribute__((packed));
65
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +053066/** @brief implements the set user access command
67 * @param ctx - IPMI context pointer (for channel)
68 * @param channel - channel number
69 * @param ipmiEnabled - indicates ipmi messaging state
70 * @param linkAuthEnabled - indicates link authentication state
71 * @param accessCallback - indicates callback state
72 * @param bitsUpdate - indicates update request
73 * @param userId - user id
74 * @param reserved1 - skip 2 bits
75 * @param privilege - user privilege
76 * @param reserved2 - skip 4 bits
77 * @param sessionLimit - optional - unused for now
78 *
79 * @returns ipmi completion code
80 */
81ipmi::RspType<> ipmiSetUserAccess(ipmi::Context::ptr ctx, uint4_t channel,
82 uint1_t ipmiEnabled, uint1_t linkAuthEnabled,
83 uint1_t accessCallback, uint1_t bitsUpdate,
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +053084
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +053085 uint6_t userId, uint2_t reserved1,
86
87 uint4_t privilege, uint4_t reserved2,
88
89 std::optional<uint8_t> sessionLimit)
90{
91 uint8_t sessLimit = sessionLimit.value_or(0);
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +000092 if (reserved1 || reserved2 || sessLimit ||
93 !ipmiUserIsValidPrivilege(static_cast<uint8_t>(privilege)))
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +053094 {
95 log<level::DEBUG>("Set user access - Invalid field in request");
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +053096 return ipmi::responseInvalidFieldRequest();
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +053097 }
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +000098
99 uint8_t chNum =
100 convertCurrentChannelNum(static_cast<uint8_t>(channel), ctx->channel);
101 if (!isValidChannel(chNum))
102 {
103 log<level::DEBUG>("Set user access - Invalid channel request");
104 return ipmi::response(invalidChannel);
105 }
106 if (getChannelSessionSupport(chNum) == EChannelSessSupported::none)
107 {
108 log<level::DEBUG>("Set user access - No support on channel");
109 return ipmi::response(ccActionNotSupportedForChannel);
110 }
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530111 if (!ipmiUserIsValidUserId(static_cast<uint8_t>(userId)))
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530112 {
113 log<level::DEBUG>("Set user access - Parameter out of range");
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530114 return ipmi::responseParmOutOfRange();
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530115 }
Richard Marian Thomaiyar06df8762018-12-08 17:38:25 +0530116
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530117 PrivAccess privAccess = {0};
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530118 if (bitsUpdate)
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530119 {
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530120 privAccess.ipmiEnabled = static_cast<uint8_t>(ipmiEnabled);
121 privAccess.linkAuthEnabled = static_cast<uint8_t>(linkAuthEnabled);
122 privAccess.accessCallback = static_cast<uint8_t>(accessCallback);
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530123 }
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530124 privAccess.privilege = static_cast<uint8_t>(privilege);
125 return ipmi::response(
126 ipmiUserSetPrivilegeAccess(static_cast<uint8_t>(userId), chNum,
127 privAccess, static_cast<bool>(bitsUpdate)));
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530128}
129
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530130/** @brief implements the set user access command
131 * @param ctx - IPMI context pointer (for channel)
132 * @param channel - channel number
133 * @param reserved1 - skip 4 bits
134 * @param userId - user id
135 * @param reserved2 - skip 2 bits
136 *
137 * @returns ipmi completion code plus response data
138 * - maxChUsers - max channel users
139 * - reserved1 - skip 2 bits
140 * - enabledUsers - enabled users count
141 * - enabledStatus - enabled status
142 * - fixedUsers - fixed users count
143 * - reserved2 - skip 2 bits
144 * - privilege - user privilege
145 * - ipmiEnabled - ipmi messaging state
146 * - linkAuthEnabled - link authenticatin state
147 * - accessCallback - callback state
148 * - reserved - skip 1 bit
149 */
150ipmi::RspType<uint6_t, // max channel users
151 uint2_t, // reserved1
152
153 uint6_t, // enabled users count
154 uint2_t, // enabled status
155
156 uint6_t, // fixed users count
157 uint2_t, // reserved2
158
159 uint4_t, // privilege
160 uint1_t, // ipmi messaging state
161 uint1_t, // link authentication state
162 uint1_t, // access callback state
163 uint1_t // reserved3
164 >
165 ipmiGetUserAccess(ipmi::Context::ptr ctx, uint4_t channel,
166 uint4_t reserved1,
167
168 uint6_t userId, uint2_t reserved2)
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530169{
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530170 uint8_t chNum =
Vernon Mauery5ed39592019-05-14 09:16:53 -0700171 convertCurrentChannelNum(static_cast<uint8_t>(channel), ctx->channel);
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +0000172
173 if (reserved1 || reserved2 || !isValidChannel(chNum))
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530174 {
175 log<level::DEBUG>("Get user access - Invalid field in request");
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530176 return ipmi::responseInvalidFieldRequest();
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530177 }
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +0000178
179 if (getChannelSessionSupport(chNum) == EChannelSessSupported::none)
180 {
181 log<level::DEBUG>("Get user access - No support on channel");
182 return ipmi::response(ccActionNotSupportedForChannel);
183 }
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530184 if (!ipmiUserIsValidUserId(static_cast<uint8_t>(userId)))
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530185 {
186 log<level::DEBUG>("Get user access - Parameter out of range");
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530187 return ipmi::responseParmOutOfRange();
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530188 }
189
190 uint8_t maxChUsers = 0, enabledUsers = 0, fixedUsers = 0;
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530191 ipmi::Cc retStatus;
Richard Marian Thomaiyarb6771e02019-01-29 14:42:44 +0530192 retStatus = ipmiUserGetAllCounts(maxChUsers, enabledUsers, fixedUsers);
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000193 if (retStatus != ccSuccess)
Richard Marian Thomaiyarb6771e02019-01-29 14:42:44 +0530194 {
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530195 return ipmi::response(retStatus);
Richard Marian Thomaiyarb6771e02019-01-29 14:42:44 +0530196 }
197
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530198 bool enabledState = false;
199 retStatus =
200 ipmiUserCheckEnabled(static_cast<uint8_t>(userId), enabledState);
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000201 if (retStatus != ccSuccess)
Richard Marian Thomaiyarb6771e02019-01-29 14:42:44 +0530202 {
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530203 return ipmi::response(retStatus);
Richard Marian Thomaiyarb6771e02019-01-29 14:42:44 +0530204 }
205
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530206 uint2_t enabledStatus = enabledState ? userIdEnabledViaSetPassword
207 : userIdDisabledViaSetPassword;
208 PrivAccess privAccess{};
209 retStatus = ipmiUserGetPrivilegeAccess(static_cast<uint8_t>(userId), chNum,
210 privAccess);
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000211 if (retStatus != ccSuccess)
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530212 {
213 return ipmi::response(retStatus);
214 }
215 constexpr uint2_t res2Bits = 0;
216 return ipmi::responseSuccess(
217 static_cast<uint6_t>(maxChUsers), res2Bits,
218
219 static_cast<uint6_t>(enabledUsers), enabledStatus,
220
221 static_cast<uint6_t>(fixedUsers), res2Bits,
222
223 static_cast<uint4_t>(privAccess.privilege),
224 static_cast<uint1_t>(privAccess.ipmiEnabled),
225 static_cast<uint1_t>(privAccess.linkAuthEnabled),
226 static_cast<uint1_t>(privAccess.accessCallback),
227 static_cast<uint1_t>(privAccess.reserved));
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530228}
229
Vernon Maueryac30b392021-08-05 11:08:23 -0700230/** @brief implementes the get user name command
231 * @param[in] ctx - ipmi command context
232 * @param[in] userId - 6-bit user ID
233 * @param[in] reserved - 2-bits reserved
234 * @param[in] name - 16-byte array for username
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530235
Vernon Maueryac30b392021-08-05 11:08:23 -0700236 * @returns ipmi response
237 */
238ipmi::RspType<>
239 ipmiSetUserName(ipmi::Context::ptr ctx, uint6_t id, uint2_t reserved,
240 const std::array<uint8_t, ipmi::ipmiMaxUserName>& name)
241{
242 if (reserved)
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530243 {
Vernon Maueryac30b392021-08-05 11:08:23 -0700244 return ipmi::responseInvalidFieldRequest();
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530245 }
Vernon Maueryac30b392021-08-05 11:08:23 -0700246 uint8_t userId = static_cast<uint8_t>(id);
247 if (!ipmiUserIsValidUserId(userId))
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530248 {
249 log<level::DEBUG>("Set user name - Invalid user id");
Vernon Maueryac30b392021-08-05 11:08:23 -0700250 return ipmi::responseParmOutOfRange();
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530251 }
252
Vernon Maueryac30b392021-08-05 11:08:23 -0700253 size_t nameLen = strnlen(reinterpret_cast<const char*>(name.data()),
254 ipmi::ipmiMaxUserName);
255 const std::string strUserName(reinterpret_cast<const char*>(name.data()),
jayaprakash Mutyalacdcdf2b2020-03-28 00:12:05 +0000256 nameLen);
257
Vernon Maueryac30b392021-08-05 11:08:23 -0700258 ipmi::Cc res = ipmiUserSetUserName(userId, strUserName);
259 return ipmi::response(res);
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530260}
261
262/** @brief implementes the get user name command
Vernon Mauery3c89de12021-08-05 11:08:23 -0700263 * @param[in] ctx - ipmi command context
264 * @param[in] userId - 6-bit user ID
265 * @param[in] reserved - 2-bits reserved
266
267 * @returns ipmi response with 16-byte username
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530268 */
Vernon Mauery3c89de12021-08-05 11:08:23 -0700269ipmi::RspType<std::array<uint8_t, ipmi::ipmiMaxUserName>> // user name
270 ipmiGetUserName(ipmi::Context::ptr ctx, uint6_t id, uint2_t reserved)
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530271{
Vernon Mauery3c89de12021-08-05 11:08:23 -0700272 if (reserved)
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530273 {
Vernon Mauery3c89de12021-08-05 11:08:23 -0700274 return ipmi::responseInvalidFieldRequest();
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530275 }
276
Vernon Mauery3c89de12021-08-05 11:08:23 -0700277 uint8_t userId = static_cast<uint8_t>(id);
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530278 std::string userName;
Vernon Mauery3c89de12021-08-05 11:08:23 -0700279 if (ipmiUserGetUserName(userId, userName) != ccSuccess)
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530280 { // Invalid User ID
Vernon Mauery3c89de12021-08-05 11:08:23 -0700281 log<level::DEBUG>("User Name not found", entry("USER-ID=%u", userId));
282 return ipmi::responseParmOutOfRange();
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530283 }
Vernon Mauery3c89de12021-08-05 11:08:23 -0700284 // copy the std::string into a fixed array
285 if (userName.size() > ipmi::ipmiMaxUserName)
286 {
287 return ipmi::responseUnspecifiedError();
288 }
289 std::array<uint8_t, ipmi::ipmiMaxUserName> userNameFixed;
290 std::fill(userNameFixed.begin(), userNameFixed.end(), 0);
291 std::copy(userName.begin(), userName.end(), userNameFixed.begin());
292 return ipmi::responseSuccess(std::move(userNameFixed));
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530293}
294
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530295/** @brief implementes the set user password command
296 * @param[in] netfn - specifies netfn.
297 * @param[in] cmd - specifies cmd number.
298 * @param[in] request - pointer to request data.
299 * @param[in, out] dataLen - specifies request data length, and returns
300 * response data length.
301 * @param[in] context - ipmi context.
302 * @returns ipmi completion code.
303 */
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000304Cc ipmiSetUserPassword(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
305 ipmi_request_t request, ipmi_response_t response,
306 ipmi_data_len_t dataLen, ipmi_context_t context)
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530307{
308 const SetUserPasswordReq* req = static_cast<SetUserPasswordReq*>(request);
309 size_t reqLength = *dataLen;
310 // subtract 2 bytes header to know the password length - including NULL
311 uint8_t passwordLength = *dataLen - 2;
312 *dataLen = 0;
Snehalatha Venkatesh37b1d1a2021-06-28 10:13:37 +0000313 if (req->reserved1 || req->reserved2)
314 {
315 log<level::DEBUG>("Invalid data field in request");
316 return ccInvalidFieldRequest;
317 }
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530318
319 // verify input length based on operation. Required password size is 20
320 // bytes as we support only IPMI 2.0, but in order to be compatible with
321 // tools, accept 16 bytes of password size too.
322 if (reqLength < 2 ||
323 // If enable / disable user, reqLength has to be >=2 & <= 22
324 ((req->operation == disableUser || req->operation == enableUser) &&
325 ((reqLength < 2) || (reqLength > sizeof(SetUserPasswordReq)))))
326 {
327 log<level::DEBUG>("Invalid Length");
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000328 return ccReqDataLenInvalid;
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530329 }
330 // If set / test password then password length has to be 16 or 20 bytes
Richard Marian Thomaiyar23df06f2019-01-04 16:42:22 +0530331 // based on the password size bit.
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530332 if (((req->operation == setPassword) || (req->operation == testPassword)) &&
Richard Marian Thomaiyar23df06f2019-01-04 16:42:22 +0530333 (((req->ipmi20 == passwordKeySize20) &&
334 (passwordLength != maxIpmi20PasswordSize)) ||
335 ((req->ipmi20 == passwordKeySize16) &&
336 (passwordLength != maxIpmi15PasswordSize))))
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530337 {
338 log<level::DEBUG>("Invalid Length");
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000339 return ccReqDataLenInvalid;
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530340 }
341
342 std::string userName;
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000343 if (ipmiUserGetUserName(req->userId, userName) != ccSuccess)
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530344 {
345 log<level::DEBUG>("User Name not found",
Ayushi Smriti05ad3412019-10-16 16:10:18 +0530346 entry("USER-ID=%d", (uint8_t)req->userId));
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000347 return ccParmOutOfRange;
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530348 }
349 if (req->operation == setPassword)
350 {
Suryakanth Sekar90b00c72019-01-16 10:37:57 +0530351 return ipmiUserSetUserPassword(
352 req->userId, reinterpret_cast<const char*>(req->userPassword));
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530353 }
Richard Marian Thomaiyar282e79b2018-11-13 19:00:58 +0530354 else if (req->operation == enableUser || req->operation == disableUser)
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530355 {
Richard Marian Thomaiyar282e79b2018-11-13 19:00:58 +0530356 return ipmiUserUpdateEnabledState(req->userId,
357 static_cast<bool>(req->operation));
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530358 }
Richard Marian Thomaiyar282e79b2018-11-13 19:00:58 +0530359 else if (req->operation == testPassword)
360 {
361 auto password = ipmiUserGetPassword(userName);
362 std::string testPassword(
363 reinterpret_cast<const char*>(req->userPassword), 0,
364 passwordLength);
365 // Note: For security reasons password size won't be compared and
366 // wrong password size completion code will not be returned if size
367 // doesn't match as specified in IPMI specification.
368 if (password != testPassword)
369 {
370 log<level::DEBUG>("Test password failed",
Ayushi Smriti05ad3412019-10-16 16:10:18 +0530371 entry("USER-ID=%d", (uint8_t)req->userId));
Jayaprakash Mutyala70bd0632020-10-23 06:24:55 +0000372 // Clear sensitive data
gokulsankerd6d567a2021-07-23 19:36:46 +0530373 OPENSSL_cleanse(testPassword.data(), testPassword.length());
374 OPENSSL_cleanse(password.data(), password.length());
Jayaprakash Mutyala70bd0632020-10-23 06:24:55 +0000375
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000376 return static_cast<Cc>(
Richard Marian Thomaiyar282e79b2018-11-13 19:00:58 +0530377 IPMISetPasswordReturnCodes::ipmiCCPasswdFailMismatch);
378 }
Jayaprakash Mutyala70bd0632020-10-23 06:24:55 +0000379 // Clear sensitive data
gokulsankerd6d567a2021-07-23 19:36:46 +0530380 OPENSSL_cleanse(testPassword.data(), testPassword.length());
381 OPENSSL_cleanse(password.data(), password.length());
Jayaprakash Mutyala70bd0632020-10-23 06:24:55 +0000382
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000383 return ccSuccess;
Richard Marian Thomaiyar282e79b2018-11-13 19:00:58 +0530384 }
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000385 return ccInvalidFieldRequest;
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530386}
387
smritic46f6cd2019-03-20 14:09:41 +0530388/** @brief implements the get channel authentication command
389 * @param ctx - IPMI context pointer (for channel)
390 * @param extData - get IPMI 2.0 extended data
391 * @param reserved1 - skip 3 bits
392 * @param chNum - channel number to get info about
393 * @param reserved2 - skip 4 bits
394 * @param privLevel - requested privilege level
395
396 * @returns ipmi completion code plus response data
397 * - channel number
398 * - rmcpAuthTypes - RMCP auth types (IPMI 1.5)
399 * - reserved1
400 * - extDataSupport - true for IPMI 2.0 extensions
401 * - anonymousLogin - true for anonymous login enabled
402 * - nullUsers - true for null user names enabled
403 * - nonNullUsers - true for non-null usernames enabled
404 * - userAuth - false for user authentication enabled
405 * - perMessageAuth - false for per message authentication enabled
406 * - KGStatus - true for Kg required for authentication
407 * - reserved2
408 * - rmcp - RMCP (IPMI 1.5) connection support
409 * - rmcpp - RMCP+ (IPMI 2.0) connection support
410 * - reserved3
411 * - oemID - OEM IANA of any OEM auth support
412 * - oemAuxillary - OEM data for auth
413 */
414ipmi::RspType<uint8_t, // channel number
415 uint6_t, // rmcpAuthTypes
416 bool, // reserved1
417 bool, // extDataSupport
418 bool, // anonymousLogin
419 bool, // nullUsers
420 bool, // nonNullUsers
421 bool, // userAuth
422 bool, // perMessageAuth
423 bool, // KGStatus
424 uint2_t, // reserved2
425 bool, // rmcp
426 bool, // rmcpp
427 uint6_t, // reserved3
428 uint24_t, // oemID
429 uint8_t // oemAuxillary
430 >
431 ipmiGetChannelAuthenticationCapabilities(ipmi::Context::ptr ctx,
432 uint4_t chNum, uint3_t reserved1,
433 bool extData, uint4_t privLevel,
434 uint4_t reserved2)
435{
smritic46f6cd2019-03-20 14:09:41 +0530436 uint8_t channel =
Vernon Mauery5ed39592019-05-14 09:16:53 -0700437 convertCurrentChannelNum(static_cast<uint8_t>(chNum), ctx->channel);
smritic46f6cd2019-03-20 14:09:41 +0530438
439 if (reserved1 || reserved2 || !isValidChannel(channel) ||
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +0000440 !isValidPrivLimit(static_cast<uint8_t>(privLevel)))
smritic46f6cd2019-03-20 14:09:41 +0530441 {
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +0000442 log<level::DEBUG>(
443 "Get channel auth capabilities - Invalid field in request");
444 return ipmi::responseInvalidFieldRequest();
445 }
446
447 if (getChannelSessionSupport(channel) == EChannelSessSupported::none)
448 {
449 log<level::DEBUG>(
450 "Get channel auth capabilities - No support on channel");
451 return ipmi::response(ccActionNotSupportedForChannel);
smritic46f6cd2019-03-20 14:09:41 +0530452 }
453
454 constexpr bool extDataSupport = true; // true for IPMI 2.0 extensions
455 constexpr bool reserved3 = false;
456 constexpr uint6_t rmcpAuthTypes = 0; // IPMI 1.5 auth types - not supported
457 constexpr uint2_t reserved4 = 0;
458 constexpr bool KGStatus = false; // Not supporting now.
459 constexpr bool perMessageAuth = false; // Per message auth - enabled
460 constexpr bool userAuth = false; // User authentication - enabled
461 constexpr bool nullUsers = false; // Null user names - not supported
462 constexpr bool anonymousLogin = false; // Anonymous login - not supported
463 constexpr uint6_t reserved5 = 0;
464 constexpr bool rmcpp = true; // IPMI 2.0 - supported
465 constexpr bool rmcp = false; // IPMI 1.5 - not supported
466 constexpr uint24_t oemID = 0;
467 constexpr uint8_t oemAuxillary = 0;
468
469 bool nonNullUsers = 0;
470 uint8_t maxChUsers = 0, enabledUsers = 0, fixedUsers = 0;
471 ipmi::ipmiUserGetAllCounts(maxChUsers, enabledUsers, fixedUsers);
472 nonNullUsers = enabledUsers > 0;
473
474 return ipmi::responseSuccess(
475 channel, rmcpAuthTypes, reserved3, extDataSupport, anonymousLogin,
476 nullUsers, nonNullUsers, userAuth, perMessageAuth, KGStatus, reserved4,
477 rmcp, rmcpp, reserved5, oemID, oemAuxillary);
478}
479
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000480/** @brief implements the set user payload access command.
481 * @param ctx - IPMI context pointer (for channel)
482 * @param channel - channel number (4 bits)
483 * @param reserved1 - skip 4 bits
484 * @param userId - user id (6 bits)
485 * @param operation - access ENABLE /DISABLE. (2 bits)
486 * @param stdPayload0 - IPMI - reserved. (1 bit)
487 * @param stdPayload1 - SOL. (1 bit)
488 * @param stdPayload2 - (1 bit)
489 * @param stdPayload3 - (1 bit)
490 * @param stdPayload4 - (1 bit)
491 * @param stdPayload5 - (1 bit)
492 * @param stdPayload6 - (1 bit)
493 * @param stdPayload7 - (1 bit)
494 * @param stdPayloadEnables2Reserved - (8 bits)
495 * @param oemPayload0 - (1 bit)
496 * @param oemPayload1 - (1 bit)
497 * @param oemPayload2 - (1 bit)
498 * @param oemPayload3 - (1 bit)
499 * @param oemPayload4 - (1 bit)
500 * @param oemPayload5 - (1 bit)
501 * @param oemPayload6 - (1 bit)
502 * @param oemPayload7 - (1 bit)
503 * @param oemPayloadEnables2Reserved - (8 bits)
504 *
505 * @returns IPMI completion code
506 */
507ipmi::RspType<> ipmiSetUserPayloadAccess(
508 ipmi::Context::ptr ctx,
509
510 uint4_t channel, uint4_t reserved,
511
512 uint6_t userId, uint2_t operation,
513
514 bool stdPayload0ipmiReserved, bool stdPayload1SOL, bool stdPayload2,
515 bool stdPayload3, bool stdPayload4, bool stdPayload5, bool stdPayload6,
516 bool stdPayload7,
517
518 uint8_t stdPayloadEnables2Reserved,
519
520 bool oemPayload0, bool oemPayload1, bool oemPayload2, bool oemPayload3,
521 bool oemPayload4, bool oemPayload5, bool oemPayload6, bool oemPayload7,
522
523 uint8_t oemPayloadEnables2Reserved)
524{
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +0000525 auto chNum =
526 convertCurrentChannelNum(static_cast<uint8_t>(channel), ctx->channel);
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000527 // Validate the reserved args. Only SOL payload is supported as on date.
528 if (reserved || stdPayload0ipmiReserved || stdPayload2 || stdPayload3 ||
529 stdPayload4 || stdPayload5 || stdPayload6 || stdPayload7 ||
530 oemPayload0 || oemPayload1 || oemPayload2 || oemPayload3 ||
531 oemPayload4 || oemPayload5 || oemPayload6 || oemPayload7 ||
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +0000532 stdPayloadEnables2Reserved || oemPayloadEnables2Reserved ||
533 !isValidChannel(chNum))
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000534 {
535 return ipmi::responseInvalidFieldRequest();
536 }
537
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +0000538 if ((operation != enableOperation && operation != disableOperation))
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000539 {
540 return ipmi::responseInvalidFieldRequest();
541 }
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +0000542 if (getChannelSessionSupport(chNum) == EChannelSessSupported::none)
543 {
544 return ipmi::response(ccActionNotSupportedForChannel);
545 }
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000546 if (!ipmiUserIsValidUserId(static_cast<uint8_t>(userId)))
547 {
548 return ipmi::responseParmOutOfRange();
549 }
550
551 PayloadAccess payloadAccess = {0};
552 payloadAccess.stdPayloadEnables1[1] = stdPayload1SOL;
553
554 return ipmi::response(ipmiUserSetUserPayloadAccess(
555 chNum, static_cast<uint8_t>(operation), static_cast<uint8_t>(userId),
556 payloadAccess));
557}
558
559/** @brief implements the get user payload access command
560 * This command returns information about user payload enable settings
561 * that were set using the 'Set User Payload Access' Command.
562 *
563 * @param ctx - IPMI context pointer (for channel)
564 * @param channel - channel number
565 * @param reserved1 - skip 4 bits
566 * @param userId - user id
567 * @param reserved2 - skip 2 bits
568 *
569 * @returns IPMI completion code plus response data
570 * - stdPayload0ipmiReserved - IPMI payload (reserved).
571 * - stdPayload1SOL - SOL payload
572 * - stdPayload2
573 * - stdPayload3
574 * - stdPayload4
575 * - stdPayload5
576 * - stdPayload6
577 * - stdPayload7
578
579 * - stdPayloadEnables2Reserved - Reserved.
580
581 * - oemPayload0
582 * - oemPayload1
583 * - oemPayload2
584 * - oemPayload3
585 * - oemPayload4
586 * - oemPayload5
587 * - oemPayload6
588 * - oemPayload7
589
590 * - oemPayloadEnables2Reserved - Reserved
591 */
592ipmi::RspType<bool, // stdPayload0ipmiReserved
593 bool, // stdPayload1SOL
594 bool, // stdPayload2
595 bool, // stdPayload3
596 bool, // stdPayload4
597 bool, // stdPayload5
598 bool, // stdPayload6
599 bool, // stdPayload7
600
601 uint8_t, // stdPayloadEnables2Reserved
602
603 bool, // oemPayload0
604 bool, // oemPayload1
605 bool, // oemPayload2
606 bool, // oemPayload3
607 bool, // oemPayload4
608 bool, // oemPayload5
609 bool, // oemPayload6
610 bool, // oemPayload7
611
612 uint8_t // oemPayloadEnables2Reserved
613 >
614 ipmiGetUserPayloadAccess(ipmi::Context::ptr ctx,
615
616 uint4_t channel, uint4_t reserved1,
617
618 uint6_t userId, uint2_t reserved2)
619{
620 uint8_t chNum =
621 convertCurrentChannelNum(static_cast<uint8_t>(channel), ctx->channel);
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +0000622
623 if (reserved1 || reserved2 || !isValidChannel(chNum))
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000624 {
625 return ipmi::responseInvalidFieldRequest();
626 }
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +0000627 if (getChannelSessionSupport(chNum) == EChannelSessSupported::none)
628 {
629 return ipmi::response(ccActionNotSupportedForChannel);
630 }
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000631 if (!ipmiUserIsValidUserId(static_cast<uint8_t>(userId)))
632 {
633 return ipmi::responseParmOutOfRange();
634 }
635
636 ipmi::Cc retStatus;
637 PayloadAccess payloadAccess = {};
638 retStatus = ipmiUserGetUserPayloadAccess(
639 chNum, static_cast<uint8_t>(userId), payloadAccess);
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000640 if (retStatus != ccSuccess)
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000641 {
642 return ipmi::response(retStatus);
643 }
644 constexpr uint8_t res8bits = 0;
645 return ipmi::responseSuccess(payloadAccess.stdPayloadEnables1.test(0),
646 payloadAccess.stdPayloadEnables1.test(1),
647 payloadAccess.stdPayloadEnables1.test(2),
648 payloadAccess.stdPayloadEnables1.test(3),
649 payloadAccess.stdPayloadEnables1.test(4),
650 payloadAccess.stdPayloadEnables1.test(5),
651 payloadAccess.stdPayloadEnables1.test(6),
652 payloadAccess.stdPayloadEnables1.test(7),
653
654 res8bits,
655
656 payloadAccess.oemPayloadEnables1.test(0),
657 payloadAccess.oemPayloadEnables1.test(1),
658 payloadAccess.oemPayloadEnables1.test(2),
659 payloadAccess.oemPayloadEnables1.test(3),
660 payloadAccess.oemPayloadEnables1.test(4),
661 payloadAccess.oemPayloadEnables1.test(5),
662 payloadAccess.oemPayloadEnables1.test(6),
663 payloadAccess.oemPayloadEnables1.test(7),
664
665 res8bits);
666}
667
William A. Kennington III343d0612018-12-10 15:56:24 -0800668void registerUserIpmiFunctions() __attribute__((constructor));
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530669void registerUserIpmiFunctions()
670{
Richard Marian Thomaiyar0be80bd2020-01-10 12:20:16 +0530671 post_work([]() { ipmiUserInit(); });
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530672 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
673 ipmi::app::cmdSetUserAccessCommand,
674 ipmi::Privilege::Admin, ipmiSetUserAccess);
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530675
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530676 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
677 ipmi::app::cmdGetUserAccessCommand,
678 ipmi::Privilege::Operator, ipmiGetUserAccess);
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530679
Vernon Mauery3c89de12021-08-05 11:08:23 -0700680 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
681 ipmi::app::cmdGetUserNameCommand,
682 ipmi::Privilege::Operator, ipmiGetUserName);
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530683
Vernon Maueryac30b392021-08-05 11:08:23 -0700684 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
685 ipmi::app::cmdSetUserName, ipmi::Privilege::Admin,
686 ipmiSetUserName);
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530687
688 ipmi_register_callback(NETFUN_APP, IPMI_CMD_SET_USER_PASSWORD, NULL,
689 ipmiSetUserPassword, PRIVILEGE_ADMIN);
690
smritic46f6cd2019-03-20 14:09:41 +0530691 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
692 ipmi::app::cmdGetChannelAuthCapabilities,
693 ipmi::Privilege::Callback,
694 ipmiGetChannelAuthenticationCapabilities);
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000695
696 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
697 ipmi::app::cmdSetUserPayloadAccess,
698 ipmi::Privilege::Admin, ipmiSetUserPayloadAccess);
699
700 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
701 ipmi::app::cmdGetUserPayloadAccess,
702 ipmi::Privilege::Operator, ipmiGetUserPayloadAccess);
703
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530704 return;
705}
706} // namespace ipmi